记2024-08原生微信小程序开发

news2024/9/22 19:44:59

继2024.08

最近需要开发一个微信小程序的一个功能模块,但是之前在学的时候都是好几年前的东东了,然后重新快速过了一遍b站大学的教程,这篇文章就是基于教程进行的一些总结,和自己开发过程当中使用到的一些点和一些技巧什么的吧。

快速编写样式

在vscode当中安装cssTree插件,之后在wxml当中全选当前写好的代码,ctrl+ship+p调出插件选择对应cssTree插件,就会生成一个less文件,这个文件里面就是根据class类名生成的样式结构树

再安装 Easy less插件,在vscode设置当中选择插件配置打开setting文件。添加less编译配置。之后当保存了index.less之后就会同步生成到index.wxss当中

  "less.compile": {
    "compress": false, //是否压缩
    "sourceMap": false, //是否生成map文件,有了这个可以在调试台看到less行数
    "out": true, // 是否输出css文件,false为不输出,千万不要是false
    "outExt": ".wxss" // 输出文件的后缀,小程序可以写'.wxss'
    // "outExt": ".css", // 输出文件的后缀,小程序可以写'.wxss'
  }

路径别名

使用 resolveAlias 配置项用来自定义模块路径的映射规则。配置了之后,会对 require 里的模块路径进行规则匹配并映射成配置的路径。在app.json当中添加以下配置,表示使用@符号就是这个app.json的根路径(其实也就是我们的业务代码下的根路径了)resolveAlias对应的文档

	"resolveAlias": {
		"@/*": "/*"
	}

构建npm

先给小程序项目初始化一个npm和安装一个UI库,而后在开发者工具当中选择工具->构建npm,构建完成之后就会有我们的老朋友node_modules了

npm init
npm i @vant/weapp

拆分

为了将小程序代码和npm相关的文件进行分开,在根目录下新增miniprogram文件夹,将小程序相关代码放到该文件夹当中,那么外面就只有以下几个文件了。

  • .eslintrc.js
  • package.json
  • package-lock.json
  • project.cofig.json
  • project.private.config.json

配置

将文件都分开之后在project.config.json当中对文件进行配置,新增和修改了这些:也就是将原本在根目录下允许的小程序换到了miniprogram目录下

  • compileType
  • miniprogramRoot
  • setting当中的packNpmManually和packNpmRelationList
{
  "compileType": "miniprogram",
  "miniprogramRoot": "miniprogram/",
  "libVersion": "trial",
  "packOptions": {
    "ignore": [],
    "include": []
  },
  "setting": {
    "packNpmManually": true,
    "packNpmRelationList": [
      {
        "packageJsonPath": "./package.json",
        "miniprogramNpmDistDir": "./miniprogram"
      }
    ],
    "coverView": true,
    "es6": true,
    "postcss": true,
    "minified": true,
    "enhance": true,
    "showShadowRootInWxmlPanel": true,
    "babelSetting": {
      "ignore": [],
      "disablePlugins": [],
      "outputPath": ""
    }
  },
  "condition": {},
  "editorSetting": {
    "tabIndent": "auto",
    "tabSize": 2
  },
  "appid": "你的APPID",
  "srcMiniprogramRoot": "miniprogram/"
}

使用UI库

在微信小程序当中推荐了一个WeUI。但是组件还是少了些,这里使用一个Vant Weapp

// 安装库、安装完成之后需要重新构建npm,见上一个构建npm章节
npm i @vant/weapp
  • 将 app.json 中的 "style": "v2" 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
  • 引入组件,在app.json当中引入就是全局注册、在对应pages下的json引入就是局部引入
"usingComponents": {
  "van-button": "@vant/weapp/button/index"
}

分包

在小程序开发当中由于对项目包体积大小有规定,而项目越来越大的时候分包就必不可少了。在pages(也就是所有存放页面的目录)同级新增一个modules目录用来表示子包(其他业务页面)同时在app.json当中添加配置

  "subpackages": [
    {
      "root": "modules/data",
      "name": "数据",
      "pages": [
        "pages/list/index",
        "pages/my/index"
      ]
    }
  ]

这个时候打包之后在modeles当中data(数据子包)就会进行分开打包。选择详情->基本信息->本地代码->代码依赖分析查看结果

分包预下载

规则配置,表示在进入pages/index页面之前先将modules分包下载下来,不论是在WIFI还是流量的网络下。

  "preloadRule": {
    "pages/index": {
      "network": "all",
      "packages": ["modules"]
    }
  }

交互封装

Loading

const defaultOptions = {
  title: "加载中",
  mask: true,
};

/**
 * 统一封装原生loading效果
 * @param {Object} options 配置选项
 * @param {string} options.title 提示的标题
 * @param {string} options.mask 是否遮罩
 */
export const showLoading = (options = {}) => {
  options = Object.assign({}, defaultOptions, options);
  wx.showLoading(options);
};

export const hideLoading = () => {
  wx.hideLoading();
};

Modal

响应Promise,使用的地方得到响应通过boo判断是确认还是取消

const defaultParams = {
  title: "提示",
  content: "这是一个模态弹窗",
  showCancel: true,
  cancelText: "取消",
  cancelColor: "#000",
  confirmText: "确定",
  confirmColor: "#576B95",
};

/**
 * 展示模态框
 * 点击了确定或者取消按钮通过回传回去,异步接收通过true or false 判断
 *
 * @param {Object} options 配置选项
 * @param {string} options.title 提示的标题
 * @param {string} options.content 提示的内容
 * @param {boolean} options.showCancel 是否显示取消按钮
 * @param {string} options.cancelText 取消按钮的文字,最多 4 个字符
 * @param {string} options.cancelColor 取消按钮的文字颜色,必须是 16 进制格式的颜色字符串
 * @param {string} options.confirmText 确认按钮的文字,最多 4 个字符
 * @param {string} options.confirmColor 确认按钮的文字颜色,必须是 16 进制格式的颜色字符串
 */
export const showModal = (params) => {
  params = Object.assign({}, defaultParams, params);
  return new Promise((resolve) => {
    wx.showModal({
      ...params,
      success(res) {
        // 点了确认res当中会有confirm,取消则是cancel
        resolve(res.confirm);
      },
    });
  });
};

Toast

const defaultOptions = {
  title: "",
  icon: "success",
  image: "",
  duration: 2000,
  mask: false,
};

/**
 * 展示提示框
 *
 * 下面是入参对象的部分配置
 * @param title 提示的内容
 * @param icon 提示的图标
 * @param image 本地图标,优先级高于icon
 * @param duration 显示延迟时间
 * @param mask 是否显示透明蒙层,防止触摸穿透
 */
export const showToast = (options) => {
  options = Object.assign({}, defaultOptions, options);
  wx.showToast(options);
};

请求封装

这里对wx.request请求进行封装,主要逻辑在于

  • 合并参数
  • 设置token
  • 发送请求
  • 请求响应后通过Promise返回,使用的地方通过async await拿到响应体
import { delLocalSync, getLocalSync } from "./localStorage";
import { showLoading, hideLoading } from "./loding";
import { showToast } from "./toast";

const baseUrl = "http://127.0.0.1";
const defaultOptions = {
  method: "GET",
  timeout: 90000,
};
/**
 * 整合一个公共发送请求接口
 * @param {Object} options
 * @param {string} method string 请求方式
 * @param {string} url string 请求地址
 * @param {number} timeout number 请求超时时间
 */

export const request = (options) => {
  options = Object.assign({}, defaultOptions, options);
  const { url, data, method, header } = options;

  showLoading();

  const token = getLocalSync("token");

  if (token) {
    header["Authorization"] = token;
  }

  return new Promise((resolve, reject) => {
    wx.request({
      url: baseUrl + url,
      method,
      data,
      header,
      success: (result) => {
        const { statusCode, data } = result;
        if (statusCode === 200) {
          resolve(result.data);
        } else if (statusCode === 400) {
          showToast({ title: data.message, icon: "none" });
        } else if (statusCode === 401) {
          delLocalSync("token");
          showToast({ title: "登录信息过期,请重新登录", icon: "none" });
        }
      },
      fail: (err) => {
        reject(err);
      },
      complete: () => {
        hideLoading();
        // 如果后端接口直接抛异常就走这个判断,再弹提示
      },
    });
  });
};

代码质量检查

在微信开发者工具当中选择 工具 -> 真机性能分析工具 运行完成之后会打开对应的代码质量tab,查看不通过的项进行修改

自定义表格

其实感觉小程序项目做表格是不太好的,可能是还是用PC端的逻辑来做的UI就会要做表格,下面是一个自定义表格和一些样式可以参考一下

<view class="table">
    <view class="table__header">
        <view class="check__cell">
            <checkbox value="cb" color="#1979FF" checked="{{false}}" />
        </view>
        <view class="card__cell">姓名</view>
        <view class="imsi__cell">年龄</view>
    </view>

    <view class="table__body">
        <view class="table__item" wx:for="{{tableData}}" wx:for-index="index" wx:for-item="item" wx:key="id">
            <view class="check__cell">
                <checkbox value="{{item.isChecked}}" color="#1979FF" checked="{{item.isChecked}}" />
            </view>
            <view class="card__cell">{{item.name}}</view>
            <view class="imsi__cell">{{item.age}}</view>
        </view>
    </view>
</view>

对应的样式

view.table {
  padding: 20rpx 20px 0 20px;

  view.table__header {
    display: flex;
    background-color: #F5F5F5;
    height: 72rpx;
    align-items: center;
    font-size: 28rpx;
    font-weight: bold;
    text-align: center;

    .check__cell {
      width: 100rpx;
    }

    .card__cell {
      width: 50%;
    }

    .imsi__cell {
      width: 50%;
    }
  }

  view.table__body {
    height: calc(100vh - 450rpx);
    overflow: scroll;
  }

  view.table__item {
    display: flex;
    height: 64rpx;
    align-items: center;
    font-size: 28rpx;
    text-align: center;

    .check__cell {
      width: 100rpx;
    }

    .card__cell {
      width: 50%;
    }

    .imsi__cell {
      width: 50%;
    }
  }
}

在这里插入图片描述

OCR文本识别

方案一:小程序插件

首先需要在微信公众平台上面 设置-> 第三方设置 -> 插件管理,添加OCR支撑这个插件。然后在详情当中有开发文档,需要先去购买限制,一天有一百次免费使用。

在app.json当中声明插件,同时图省事的话可以把包直接全局引入,也可以在要使用的页面当中注册这个组件

 "plugins": {
    "ocr-plugin": {
      "version": "3.1.3",
      "provider": "wx4418e3e031e551be"
    }
  }

  "usingComponents": {
    "ocr-navigator": "plugin://ocr-plugin/ocr-navigator"
  }

使用的话就比较简单了,这里以扫描车牌为例:

<ocr-navigator bind:onSuccess="platenumSuccess" certificateType="platenum">
    <button type="primary">车牌识别</button>
</ocr-navigator>
<view>OCR识别的车牌是:{{licensePlate}}</view>

// 在对应的js当中添加扫描成功的方法
platenumSuccess(event){
	this.setData({
		licensePlate: event.detail.number.text
	})
},

在这里插入图片描述

方案二:前端 tesseract.js

这个以Vue3的代码为例:首先需要安装npm i tesseract.js。其中第一次使用会去加载对应的资源会有一点点慢

<template>
  <div>
    <div style="marginTop:100px">
      <input id="image-input" accept="image/*" type="file" @change="handleChage">
      <br/>
      <button @click="processImage">提取文字</button>
      <div id="show-picture"></div>
    </div>
    <div>
      <p style="color:red">提取到的内容:</p>
      <span id="result"></span>
    </div>
  </div>
</template>

<script setup>
import {createWorker} from 'tesseract.js';

//将选择的图片显示在页面上
const handleChage = () => {

  document.getElementById('result').innerText = '';
  let getUserPhoto = document.getElementById('image-input');


  //创建一个FileReader对象,用于读取图像文件
  let reader = new FileReader();

  //读取第一个文件,并转为base64格式
  reader.readAsDataURL(getUserPhoto.files[0]);

  //只显示第一个图片
  reader.onload = function () {
    let image = document.createElement('img');
    image.width = '400';

    //设置图片
    image.src = reader.result;
    let showPicture = document.getElementById('show-picture');
    while (showPicture.firstChild) {
      showPicture.removeChild(showPicture.firstChild);
    }
    showPicture.appendChild(image);
  };
};


const processImage = () => {
  let worker;
  let input = document.getElementById('image-input');
  if (input.files && input.files[0]) {
    let reader = new FileReader();
    reader.onload = async function (e) {

      //创建一个Worker线程,参数为需要识别的语言, chi_sim代表简体中文
      worker = await createWorker('chi_sim');
      worker.recognize(e.target.result)
          .then(result => {

            // 提取出的文字,给元素赋值
            console.log(' =====', result);
            let extractedText = result.data.text;
            document.getElementById('result').innerText = extractedText;

          })
          .catch(error => {
            console.error('Error:', error);
          }).finally(() => {
        if (worker)

            // 清除当前Worker线程
          worker.terminate();

      });
    };
    reader.readAsDataURL(input.files[0]);
  }
};
</script>

在这里插入图片描述

方案三:java Spore.OCR

使用java实现的是使用这个Spire.OCR,代码是基于springboot来写的哈(非常感谢您使用我们的 Spire.OCR for Java 产品。试用版在功能上没有任何限制,只是在结果文档中有试用提示信息。)

先安装maven依赖,安装不下来的话就配置一下这个仓库地址

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>

<dependency>
	<groupId>e-iceblue</groupId>
	<artifactId>spire.ocr</artifactId>
	<version>1.9.0</version>
</dependency>

其他依赖文件请根据您所使用的操作系统选择下载:这个下载下来的是dependencies压缩包解压放在项目的根目录下

  • Linux(须使用 CentOS 8、Ubuntu 18 及以上版本)
  • Windows x64

利用java实现:这里直接贴代码了

package com.ocr.ocrserver.controller;

import com.spire.ocr.OcrException;
import com.spire.ocr.OcrScanner;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OcrController {

    @RequestMapping("/")
    public String home() throws OcrException {
        //指定依赖文件的路径
        String dependencies = "dependencies\\";

        String imageFile = "8.png";

        //创建OcrScanner对象,并设置其依赖文件路径
        OcrScanner scanner = new OcrScanner();
        scanner.setDependencies(dependencies);

        //扫描指定的图像文件
        scanner.scan(imageFile);

        //获取扫描的文本内容
        String scannedText = scanner.getText().toString();

        return scannedText;
    }
}

报错:Exception in thread “main” java.lang.NoClassDefFoundError: sun/misc/BASE64De

表示 Java 虚拟机(JVM)在运行时尝试加载某个类,但没有找到指定的类。这里的错误信息显示找不到的类是 sun/misc/BASE64Decoder,这是 Java 内置的类,用于进行 Base64 编码和解码。将jdk版本降到1.8。你出任你出,我用java8

在这里插入图片描述

方案四:小程序原生

在微信小程序的文档当中有一个AI视觉算法 VKOCRAnchor

使用这个也是可以实现的,首先找到他的github代码地址,把代码拉一份下来。GitHub代码。把整个仓库拉一份下来,将这个OCR的目录拷一份到自己的项目当中。需要在app.json配置对应的路径

  • 安装依赖 npm i threejs-miniprogram 安装之后构建一下
  • 在behavior.js当中还引入了…/loaders/gltf-loader,将仓库当中的这个loaders拷贝过来
  • 之后就是重新编译查看效果了,这个时候发现UI好像不一样,发现是canvas的高度太高啦,在wxml文件当中找到canvas元素将其宽高改成0,这个也是没啥用的。要是想要这个canvas展示就自己重新设置一下宽高。
  • 最后一步,发现不管是在开发工具当中编译发现报错,识别不出来?这个时候懵逼了,后面发现在手机上进行预览是正常的,难道不能在模拟器运行?

到这也就完成了这一块的功能,其中获取识别后的数据在behavior.js当中的updateAnchors回调当中

在这里插入图片描述

方案五:第三方服务

在腾讯云、阿里云、百度云都有OCR文本识别进行出售,也可以直接进行购买进行使用。

表单规则校验

在这里推荐使用async-validator,下面整个案例看一下怎么使用,先npm安装就跳过了,安装完之后记得在开发工具当中npm构建

下面简单的说明了一下使用方法,以及简单校验、正则校验、自定义校验三个规则。在校验的时候我们需要异步等待,同时如果没有通过校验的我们可以拿到errors,这个是一个数组,每一项就对应校验规则某个字段,最后只要有没通过的就resolve(false)。在提交的时候拿到这个值去判断

  • 创建规则数组
  • 实例化Schema对象,将rule传进去
  • 调用validate方法进行校验,得到error(校验未通过的项)
import Schema from "async-validator";
Page({
  /**
   * 页面的初始数据
   */
  data: {
    name: "",
    age: 18,
    email: "",
  },

  // 表单校验
  onValidate() {
    // 匹配年龄的正则(表示匹配1-150)
    const ageRegExp = /^(?:[1-9][0-9]?|1[0-4][0-9]|150)$/;

    // email 正则
    const emailRegExp =
      /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/;

    // 校验规则
    const rules = {
      name: [{ required: true, message: "姓名不能为空" }],
      // 还可以通过min max 指定最大最小值
      age: [
        { required: true, message: "年龄不能为空" },
        { pattern: ageRegExp, message: "请输入1到150之间的数" },
      ],
      email: [
        { required: true, message: "邮箱地址不能为空" },
        {
          pattern: emailRegExp,
          message: "邮箱不合法请检查",
        },
      ],
      // 自定义校验规则,和el-plus大差不大的
      emailV: [
        {
          asyncValidator: (rule, value) => {
            return new Promise((resolve, reject) => {
              console.log(value);
              if (!value) {
                reject("请输入啊,哥们");
              } else {
                resolve();
              }
            });
          },
        },
      ],
    };

    const validator = new Schema(rules);
    return new Promise((resolve) => {
      validator.validate(this.data, (errors) => {
        if (errors) {
          // 这个是封装的消息展示
          showToast({ title: errors[0].message, icon: "error" });
          resolve({ valid: false });
        } else {
          resolve({ valid: true });
        }
      });
    });
  },

  // 提交按钮触发事件
  async onSubmit() {
    const { valid } = await this.onValidate();
    if (!valid) return;
    // 验证通过,做后续业务逻辑
  },
});

在这里插入图片描述

自动化测试

自动化测试这里又涉及到了python使用测试的库是 minium 这里安装python和开发工具pycharm就调过来了哈,

首先初始化一个项目,先添加一个config.json配置文件

  • project_path 是小程序项目存放的位置
  • dev_tool_path 是微信开发者工具的位置
  • debug_mode 调试模式用debug就好了
{
  "project_path": "D:\\xxx\\xxx\\ocrprogram",
  "dev_tool_path": "D:\\soft\\wechat_devtools\\install\\wx_tools\\cli.bat",
  "debug_mode": "debug"
}

简单来个demo测试一下。先需要通过pip install minium 安装一下这个库,代码是很通俗易懂的哈,要是不会py就把他理解成js或者java代码就好了,创建一个类继承过来,然后定义方法,通过对应的方法去找元素(Ele)再触发点击事件。

import minium

class Test(minium.MiniTest):
    def test1(self):
        # 找到录入按钮模拟点击
        enter = self.page.get_element("view[class='model enter']")
        enter.click()

        # 找到下一步的按钮再模拟点击
        next = self.page.get_element("van-button[class='next']")
        next.click()

运行测试,运行之后会自动打开微信开发者工具并且预览项目指定对应的交互操作,完成之后会在py项目当中生成outputs文件夹,预览里面的index.html文件(也就是我们要的测试报告)

  • -c 指定config配置文件
  • -m 指定对应要执行的模块,也就是对应的py文件,这里可以不用跟上文件后缀
  • -g 表示生成测试报告
minitest -c config.json -m test -g

最终来说,不同的小程序测试脚本不同,实际开发还是根据实际为准,获取按钮事件、获取input焦点、添加随机字符等等。

在这里插入图片描述

触发wxAPI

在minium当中可以通过call_wx_method方法去触发原生wxAPI,下面以获取系统配置为例。通过call_wx_method调用,入参直接传wxAPI的名称,然后后面的get方法和minium没有关系,是call_wx_method响应的是一个对象,这里通过get方法把外面包的几层不要的去掉。

sys_info = self.app.call_wx_method("getSystemInfo").get("result", {}).get("result")
self.assertIsInstance(sys_info, dict, "is dict")
print('--------------系统信息------------')
print(sys_info)

# 得到结果
{'errMsg': 'getSystemInfo:ok', 'batteryLevel': 100, 'benchmarkLevel': -1, 'brand': 'devtools', 'memorySize': 2048, 'model': 'iPhone 15 Pro Max', 'system': 'iOS 10.0.1', 'platform': 'devtools', 'pixelRatio': 3, 'safeA
rea': {'top': 54, 'left': 0, 'right': 430, 'bottom': 898, 'width': 430, 'height': 844}, 'screenWidth': 430, 'screenHeight': 932, 'screenTop': 98, 'windowWidth': 430, 'windowHeight': 834, 'statusBarHeight': 54, 'versi
on': '8.0.5', 'language': 'zh_CN', 'SDKVersion': '3.5.1', 'enableDebug': False, 'fontSizeScaleFactor': 1, 'fontSizeSetting': 15, 'mode': 'default', 'host': {'env': 'WeChat'}, 'bluetoothEnabled': True, 'locationEnable
d': True, 'wifiEnabled': True, 'locationReducedAccuracy': True, 'albumAuthorized': True, 'bluetoothAuthorized': True, 'cameraAuthorized': True, 'locationAuthorized': True, 'microphoneAuthorized': True, 'notificationA
uthorized': True, 'notificationAlertAuthorized': True, 'notificationBadgeAuthorized': True, 'notificationSoundAuthorized': True, 'phoneCalendarAuthorized': True, 'deviceOrientation': 'portrait', 'devicePixelRatio': 3}

同理,我们也可以通过这个去调用加载图片

        options = {
            'count': 1,  # 最多可以选择的图片张数
            'sizeType': ['original', 'compressed'],  # 所选的图片的尺寸
            'sourceType': ['album', 'camera']  # 选择图片来源
        }

        # 调用chooseMedia方法并传入选项
        result = self.app.call_wx_method('chooseMedia', options).get("result", {}).get("result")

        # 这个时候result的值
		# {'errMsg': 'chooseMedia:ok', 'failedCount': 0, 'type': 'image', 'tempFiles': [{'tempFilePath': 'http://tmp/KfQ128Lwv8Sv19ba87032dc5c89b40f6e34ad7d9a639.jpg', 'size': 1266964, 'fileType': 'image'}]}
        
        # 处理回调结果
        if result['errMsg'] == 'chooseImage:ok':
            chosen_images = result['tempFiles']
            # 在这里添加断言或其他测试逻辑
        else:
            print("Error choosing media:", result['errMsg'])

发送邮件

方案一:node环境

在前端发送邮件可以使用nodemailer,这是在node环境当中,下面以QQ邮箱发送为例,首先登录QQ邮箱,之后在设置-账号-开启POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务,并且拿到对应的授权码

在这里插入图片描述

const nodemailer = require("nodemailer");

// 创建一个SMTP客户端配置对象
const transporter = nodemailer.createTransport({
  host: "smtp.qq.com", // QQ邮箱的SMTP服务器地址
  port: 465, // 端口号
  secure: true, // 使用SSL加密
  auth: {
    user: "12345678@qq.com", // 你的QQ邮箱账号
    pass: "授权码", // 你的QQ邮箱授权码
  },
});

// 设置邮件内容
const mailOptions = {
  from: "12345678@qq.com", // 发件人地址
  // to: '110@163.com', // 收件人地址
  to: "87654321@qq.com",
  subject: "你好,附件", // 邮件主题
  text: "对应的信息放在附件了", // 邮件正文(纯文本)
  html: "<div>时间:2024-10-10 10:00:00</div><div>编号:PC12138</div><div>名称:测试</div>", // html格式
  // 附件信息(名称和对应的路径)
  attachments: [
    {
      filename: "package.json",
      path: "./package.json",
    },
  ],
};

// 发送邮件
transporter.sendMail(mailOptions, (error, info) => {
  if (error) {
    console.log("Error sending email:", error);
  } else {
    console.log("Email sent:", info.response);
  }
});

在这里简单测试了一下发送的效果,其中接收邮箱是qq和阿里的就来挺快的和正常收发是一样的,但是用了网易163邮箱试了一下在163那边要很久才能收到通知,不知道这个是不是通知机制出问题了,还是卡了什么的,这个注意一下,后续使用的时候也记得测一测

自定义组件

在实际开发过程当中,组件的拆分是必不可少的,下面就简单的介绍一下wx组件的使用,整体结构和页面是一样的,在pages同级目录新增components用来放组件,组件需要在app.json当中进行引入,这个可以看前面使用UI库,和vantweapp一样引入即可。

组件数据传递

父组件往子组件传数据,子组件是通过Component构建的,通过properties用来接收,这个和vue就基本上是一样的,子组件本身使用数据直接用descItem即可。更多的自定义组件可以看官方API

Component({
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多slot支持
  },
  properties: {
    /**
     * 数据格式说明 数组对象[{},{},{}]
     * @param {string} batchNo 批号
     * @param {string} createTime 创建时间
     * @param {string} startLastTime 有效期开始
     * @param {string} endLastTime   有效期结束
     * @param {string} num 数量
     * @param {string} name 名称
     */
    descItem: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
  
  // 子组件本身的数据
  data: {
    
  },
  
  // 子组件往外暴露事件
  methods: {
    send(){
        this.triggerEvent("send", 1)
    },
  },
});

# 父组件传值
<Card descItem="{{item}}" bind:send="getSend" />

获取组件实例

通过this.selectComponent()方法获取实例,其中需要传子组件的选择器(id或class选择器)

this.selectComponent('.crad')

Behavior

用于组件间代码共享的特性,可以把他当成vue2当中的mixins混入,behavior文档

export default function getBehavior() {
  return Behavior({
    // 组件的对外属性,是属性名到属性设置的映射表
    properties: {
      myBehaviorProperty: {
        type: String,
      },
    },

    // 内部定义的数据
    data: {
      num: {},
    },

    // 数据字段监听器
    observers: {
      num: function (newNum) {
        console.log("num change --- ", newNum);
      },
    },

    // 组件生命周期函数
    attached: function () {},

    // 组件的方法
    methods: {
      myBehaviorMethod: function () {},
    },
  });
}

使用behavior

import getBehavior from "./behavior";
Component({
  behaviors: [getBehavior()],
});

页面数据通信

  • eventChannel
  • 事件总线

在小项目当中可以使用,在庞大的项目当中还是避免使用这个,不然数据传来传去找的头皮发麻,应该用数据变化去驱动事件

全局数据

getApp()

在小程序app.js当中会初始化一个App全局对象,就好像Vue一样,这个里面是整个的初始化生命周期、全局数据等。

// app.js
App({
  onLaunch() {},
  globalData: {
    userInfo: null
  },

  setUserInfo() {
    this.globalData.userInfo = {
      name: "admin",
    };
  },
});

如何使用全局数据

const app = getApp()

// 获取全景数据
app.globalData.userInfo

// 调用方法
app.setOcrCard({name:'zhangsan'})

Store

在vue3或者vue2开发当中我们会使用pinia或者vuex,他的基本概念就是创建一个全局的Store管理数据。那么在小程序开发当中有没有这种框架捏。这个时候就要看 mobx-miniprogram 和 mobx-miniprogram-bindings 了

import { observable, action } from 'mobx-miniprogram'
// 使用 observable 创建一个被监测的对象
export const numStore = observable({
  // 创建应用状态
  numA: 1,
  numB: 2,
    
  // 使用 action 更新 numA 以及 numB
  update: action(function () {
    this.numA+=1
    this.numB+=1
  }),
 
  // 计算属性,使用 get 修饰符,
  get sum() {
    return this.numA + this.numB;
  }
})

使用定义好的numStore的数据

// components/custom01/custom01.js
import { ComponentWithStore } from 'mobx-miniprogram-bindings'
import { numStore } from '../../stores/numstore'
 
ComponentWithStore({
  data: {
    
  },
  storeBindings: {
    store: numStore,
    fields: ['numA', 'numB', 'sum'],
    actions: ['update']
  }
})

数据监听&计算属性

小程序当中没有计算属性和监听的功能,如果想用的话可以使用 miniprogram-computed

import { ComponentWithComputed } from "miniprogram-computed";

ComponentWithComputed({
  data: {
    a: 1,
    b: 1,
  },

  computed: {
    total(data) {
      return data.a + data.b;
    },
  },

  watch: {
    a: function (a) {
      console.log(a);
    },
    // 同时对 a 和 b 进行监听
    "a, b": function (a, b) {
      this.setData({
        total: a + b,
      });
    },
  },
});

vue mini

在2024 vue conf上有对这个vue mini进行了介绍,文档地址在这。正好最近在做微信小程序就做了一些了解

  • 基于vue3,可以使用vue3当中的响应式
  • 组合式API

个人观点:后续还是要看对SFC的支持怎么样吧,现在只是把js层可以用这一层,wxml这一层还是要写原生的。不过也不妨是一个方案吧。

import { ComponentWithStore } from 'mobx-miniprogram-bindings'
import { numStore } from '../../stores/numstore'
 
ComponentWithStore({
  data: {
    
  },
  storeBindings: {
    store: numStore,
    fields: ['numA', 'numB', 'sum'],
    actions: ['update']
  }
})

数据监听&计算属性

小程序当中没有计算属性和监听的功能,如果想用的话可以使用 miniprogram-computed

import { ComponentWithComputed } from "miniprogram-computed";

ComponentWithComputed({
  data: {
    a: 1,
    b: 1,
  },

  computed: {
    total(data) {
      return data.a + data.b;
    },
  },

  watch: {
    a: function (a) {
      console.log(a);
    },
    // 同时对 a 和 b 进行监听
    "a, b": function (a, b) {
      this.setData({
        total: a + b,
      });
    },
  },
});

vue mini

在2024 vue conf上有对这个vue mini进行了介绍,文档地址在这。正好最近在做微信小程序就做了一些了解

  • 基于vue3,可以使用vue3当中的响应式
  • 组合式API

个人观点:后续还是要看对SFC的支持怎么样吧,现在只是把js层可以用这一层,wxml这一层还是要写原生的。不过也不妨是一个方案吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1996998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp小程序出现【 wxss GetCompiledResult】报错

报错信息 进入页面报错&#xff0c;导致页面无法显示 原因 查看小程序源代码发现 wxss 文件内有个不正常的字符 就是这个 * 导致解析失败 出现解析失败的原因 / 解决办法 是因为这里使用了通配符 注释掉就可以了

多组织系统的设计思路

一、什么是多组织系统 多组织这个概念是一般多用于企业信息化系统。通常是指一个集团分拆了多个子公司进行运营&#xff0c;每家子公司负责集团业务的一个到多个部分&#xff0c;多家子公司共同支撑集团的全部业务。 子公司内部&#xff0c;在业务执行过程中相对独立&#xf…

c++标准库STL————string类的基础模拟

string类 一、构造类函数1.构造一个空内容的对象2.用已知对象进行拷贝构造3.用c语言字符串的形式构造 二、容量型函数三、对象访问四、修改类操作4、非成员函数 一、构造类函数 c11提供了许多参数的重组&#xff0c;但通常这四种类型的构造较为常用。 1.构造一个空内容的对象 …

Python 机器学习求解 PDE 学习项目 基础知识(4)PyTorch 库函数使用详细案例

PyTorch 库函数使用详细案例 前言 在深度学习中&#xff0c;PyTorch 是一个广泛使用的开源机器学习库。它提供了强大的功能&#xff0c;用于构建、训练和评估深度学习模型。本文档将详细介绍如何使用以下 PyTorch 相关库函数&#xff0c;并提供相应的案例示例&#xff1a; to…

我在高职教STM32——I2C通信之读写EEPROM(1)

大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正是如此,才有了借助CSDN平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思设计的教学课件分…

日撸Java三百行(day18:循环队列)

目录 一、顺序队列与循环队列 二、代码实现 1.循环队列创建 2.循环队列遍历 3.循环队列入队 4.循环队列出队 5.数据测试 6.完整的程序代码 总结 一、顺序队列与循环队列 在昨天&#xff0c;我们提到队列实现除了采用链式存储结构&#xff0c;还可以采用顺序存储结构&…

数字电路波形图绘制工具WaveDrom简介

最近写东西的时候&#xff0c;需要画波形图&#xff0c;无意中找到了一蛮好用的工具&#xff1a;WaveDrom WaveDrom 是一个 JavaScript 应用程序。WaveJSON 是一种描述数字时序图的格式。WaveDrom 直接在浏览器内部渲染这些时序图。元素 “signal” 是一个 WaveLane 数组。每个…

NO.4 软件外包公司

今天我们来聊聊国内的四大软件外包公司。这些公司不仅在国内市场中占据重要地位&#xff0c;还对全球软件外包行业产生了影响。 部分数据来源网络排名&#xff0c;按照职位量、增长速度排名&#xff0c;排名仅供参考&#xff0c;去某家公司一定要多方位参考&#xff0c;比如企查…

uniapp基础知识【搬代码】

基础知识 HTML、css、javaScript&#xff08;ES6&#xff09; HTML结构 1.View 类似于传统html中的div&#xff0c;用于包裹各种元素内容。 2.text文本 3.swoper 4.image 5.video 6.button 7.input <template><!-- <view class"content"><imag…

泛微E-office 10 schema_mysql接口敏感信息泄露漏洞复现 [附POC]

文章目录 泛微E-office 10 schema_mysql接口敏感信息泄露漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现泛微E-office 10 schema_mysql接口敏感信息泄露漏洞复现 [附POC] 0x01 前言 免责声明:请勿利用文章内…

两篇论文同时获最佳论文荣誉提名,SIGGRAPH上首个Real-Time Live的中国团队用生成式AI创建3D世界

专注于计算机图形学的全球学术顶会 SIGGRAPH&#xff0c;正在出现新的趋势。 点击访问我的技术博客https://ai.weoknow.comhttps://ai.weoknow.com 在上周举行的 SIGGRAPH 2024 大会上&#xff0c;最佳论文等奖项中&#xff0c;来自上海科技大学 MARS 实验室的团队同时拿到两篇…

HTML表单元素

HTML表单元素 表单把用户的信息发给服务器。 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title> </head><body><form class"stylin_form1" action"process_form.php" met…

uni-app开发微信小程序注意事项,不要用element-ui

前端扩展组件千万不要用element-ui&#xff0c;开发的时候不报错&#xff0c;发布的时候会报错无法发布。 可以用vant weapp【注意是weapp】 iView weapp 附上hbuilder官方文档 组件的概念 | uni-app官网 (dcloud.net.cn)

git-贮藏区打补丁

1.显示所有贮藏 git stash list 2.将贮藏区的修改打补丁 git stash show -p stash{0} > patchName.patch commit打补丁 git 生成补丁文件及打补丁_git 生成指定目录补丁-CSDN博客 git patch的使用方法_git pattch-CSDN博客

「MyBatis」数据库相关操作

MyBatis 简介 MyBatis 是⼀个持久层框架&#xff0c;用于简化 JDBC 的开发 持久层指的就是持久化操作的层&#xff0c;通常指数据访问层 (dao)&#xff0c;是用来操作数据库的 Mapper 注解的接口表示该接口是 MyBatis 中的 Mapper 接口 回顾一下之前提到过的图 简单来说&…

如何选用合适的开源知识管理系统?10款软件推荐

国内外主流的10款开源知识管理软件对比&#xff1a;PingCode、Worktile、DokuWiki、MediaWiki、GitBook、Nuclino、Think、TiddlyWiki、AFFiNE、Foam。 在管理知识的广阔天地中&#xff0c;选择合适的工具可能会让你感到头痛。开源知识管理软件以其灵活性和成本效益在行业内脱颖…

Java设计模式-单例模式最佳实践

1. 单例模式简介 Java 单例模式是四大设计模式之一&#xff0c;属于创建型设计模式。从定义上看&#xff0c;它似乎是一种简单的设计模式&#xff0c;但在实现时&#xff0c;如若不注意&#xff0c;它会带来很多问题。 在本文中&#xff0c;我们将了解单例设计模式原则&#…

使用 GPU 加速的 XGBoost 预测出租车费用

目录 XGBoost GPU 加速的 XGBoost 用例数据集示例 将文件中的数据加载到 DataFrame 定义特征数组 保存模型 总结 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c; 可以当故事来看&#xf…

小智纯前端js报表实战5-绝对坐标-横向扩展

绝对坐标-横向扩展 概述 绝对坐标-横向扩展&#xff1a;绝对坐标定位 层次坐标是实现复杂报表的一个重要功能。 在进行小智报表模板设计时&#xff0c;单元格尚未进行扩展&#xff0c;但是有些时候需要获取扩展后的单元格并进行计算。例如&#xff0c;A1单元格扩展成A1-D1&am…

VUE+Spring前后台传值的坑,后台接收的String参数在末尾会出现 “=”

一、问题 VUESpringBoot做增删改查时&#xff0c;前端使用axios.post发起请求&#xff0c;传输主键字符型参数 taskId 到后台&#xff0c;后台再进行删除处理。 实际过程中发现后台拿到的数据再末尾多了一个等号&#xff0c;但是通过console.log(taskId)前台打印参数是正常的…