小程序开发整理

使用uni-app跨端开发框架,代码写法与vue2一致。

一、与web开发的区别1. 运行方式不同

npm run dev:mp-weixin后,用微信开发者工具打开dist中工程。

2. 标签与web开发不同

标签的对应关系

小程序中使用web中使用
viewdiv
textspan
imageimg
navigator
此外,uni-app 还提供scroll-viewswiper等内置组件。

3. 运行环境从浏览器变成v8引擎

不能使用documentwindowlocalstoragecookie等浏览器自带对象,但是可以使用 uni 提供的 api 替代。

3.1 获取dom元素

需要用到SelectorQuery 对象。

const query = uni.createSelectorQuery().in(this);query.select('#id').boundingClientRect(data => {  console.log("得到布局位置信息" + JSON.stringify(data));  console.log("节点离页面顶部的距离为" + data.top);}).exec();// select 返回 NodesRef 对象,即为节点信息。

注:我们常用的ref获取dom,不能用在uni-app内置组件上,只能用在自定义组件上。

3.2 数据缓存

本地数据缓存

// 异步uni.setStorage({key: '', data: '', success: ()=>{}, fail: ()=>{}, complete: ()=>{}})uni.getStorage({key: '', success: ()=>{}, fail: ()=>{}, complete: ()=>{}})uni.removeStorage({key: '', success: ()=>{}, fail: ()=>{}, complete: ()=>{}})uni.clearStorage()// 同步uni.setStorageSync({key: '', data: ''})uni.getStorageSync({key: ''})uni.removeStorageSync({key: ''})uni.clearStorageSync()// 获取当前 storage 相关信息uni.getStorageInfo({success: (keys, currentSize, limitSize)=>{}})const {keys, currentSize, limitSize} = uni.getStorageInfoSync();

4. 工程目录的区别

projectName/src                            ├── components    ├── pages    ├── ...    ├── pages.json                        └── manifest.json

4.1 新增 pages.json

pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、组件自动引入规则、分包加载配置、窗口样式、原生的导航栏、底部的原生tabbar 等。

1)组件自动引入规则

"easycom": {    "^tp-(.*)": "@/tp-view-ui/components/tp-$1/tp-$1.vue"},

通过uni-app的easycom,只要组件安装在项目的 components 目录下,并符合 components/组件名称/组件名称.vue 目录结构。就可以不用引用、注册,直接在页面中使用。

  • kebab-case (短横线分隔命名)
  • PascalCase (首字母大写命名)

2)页面文件路径

编译后,pages的第一个路径会成为首页

"pages": [    {        "path": "pages/index/indexA",        "style": {            "navigationBarTitleText": "AAA",            "backgroundColor": "#FFFFFF"        }    },    {        "path": "pages/index/indexB",        "style": {            "navigationBarTitleText": "BBB",            "backgroundColor": "#FFFFFF"        }    }],

3)小程序的分包加载机制

微信小程序每个分包的大小是2M,总体积一共不能超过20M。

在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,会把对应分包自动下载下来,下载完成后再进行展示。

"subPackages": [    {        "root": "pages/xxxA",        "pages": [{            "path": "list/list",            "style": {}        }]    },     {        "root": "pages/xxxB",        "pages": [{            "path": "detail/detail",            "style": {}        }]    }],

4.2 新增 manifest.json

manifest.json 文件是应用的配置文件,用于指定应用的名称、图标、权限等。

"mp-weixin": {    /* 微信小程序特有相关 */    "appid": "wx303f35140da12d22",    "setting": {        "urlCheck": true, // 检查安全域名和 TLS 版本        "minified": true, // 上传代码时自动压缩        "postcss": true, // 上传代码时样式自动补全        "es6": true // ES6 转 ES5    },    "usingComponents": true, // 全局自定义组件    "permission": { // 小程序接口权限相关设置        "scope.userLocation": {            "desc": "你的位置信息将用于小程序位置接口的效果展示"        }    }},

appid:微信小程序的AppID,登录 微信公众平台 申请。

5. CSS 注意事项5.1 像素单位

uni-app 默认为 rpx。rpx 即响应式 px,一种根据屏幕宽度自适应的动态单位。

一般UI上手机模型宽度为375px,换算关系为 1px = 2rpx。

5.2 布局

推荐使用 flex 布局。

比如上下子元素高度不固定,中间子元素占据剩余空间:

.flex {    display: flex;    flex-direction: column;    height: 600px; /* 父元素一定要指定高度 */    width: 375px;}.flex-box1 {    height: 200px;    background: #b7dff0;}.flex-box2 {    background-color: #bfa;    flex: auto;}.flex-box3 {    height: 200px;    background: #b7dff0;}

5.3 小程序组件的视图层级

组件内元素被shadow-root包裹,修改样式时需要做/deep/穿透。

二、uni-app 的生命周期1. 应用生命周期

只能在App.vue里监听应用的生命周期

函数名说明
onLaunchuni-app 初始化完成时触发(全局只触发一次)
onShowuni-app 启动,或从后台进入前台显示
onHideuni-app 从前台进入后台
onErroruni-app 报错时触发
onUniNViewMessagenvue 页面发送的数据进行监听,可参考 nvue 向 vue 通讯
onUnhandledRejection对未处理的 Promise 拒绝事件监听函数(2.8.1+)
onPageNotFound页面不存在监听函数
onThemeChange监听系统主题变化

2. 页面生命周期

函数名说明
onLoad监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参)
onShow监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
onReady监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发
onHide监听页面隐藏
onUnload监听页面卸载
onResize监听窗口尺寸变化
….

微信小程序的页面生命周期

使用 onLoad 来页面传参

//在起始页面跳转到test.vue页面并传递参数uni.navigateTo({url: 'test?id=1&name=uniapp'});
// 在test.vue页面接受参数export default {onLoad(option) { //option为object类型,会序列化上个页面传递的参数console.log(option.id); //打印出上个页面传递的参数。console.log(option.name); //打印出上个页面传递的参数。}}
  • 参数复杂的情况
uni.navigateTo({url: 'test?data=' + JSON.stringify(obj)});
onLoad: function (option) {const data = JSON.parse(option.data);}
  • 参数中出现空格等特殊字符,比如 url
uni.navigateTo({url: 'test?data=' + encodeURIComponent(JSON.stringify(obj))});
onLoad: function (option) {const data = JSON.parse(decodeURIComponent(option.data));}

除了 onLoad,还可以用 vuexuni.$on(eventName,callback)uni.$emit(eventName,OBJECT)进行页面通讯。

3. 组件生命周期

与 vue 标准组件的生命周期相同

函数名说明平台差异说明
beforeCreate在实例初始化之前被调用。
created在实例创建完成后被立即调用。
beforeMount在挂载开始之前被调用。
mounted挂载到实例上去之后调用。
beforeUpdate数据更新时调用,发生在虚拟 DOM 打补丁之前。仅H5平台支持
updated由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。仅H5平台支持
beforeDestroy实例销毁之前调用。在这一步,实例仍然完全可用。
destroyedVue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

三、特点功能整理1. 二维码显示

使用插件 tki-qrcode,uni-app 二维码生成器。

安装

npm i tki-qrcode -S

引入

import tkiQrcode from "tki-qrcode";export default {    components: {tkiQrcode}}

使用

属性

属性名类型默认值可选值说明
sizeNumber200生成的二维码大小
unitStringupxpx大小单位尺寸
valString二维码要生成的内容
lvNumber3(一般不用设置)容错级别
onvalBooleanfalse监听val值变化自动重新生成二维码
loadMakeBooleanfalse组件初始化完成后自动生成二维码,val需要有值
showLoadingBooleantruefalse是否显示loading
loadingTextString二维码生成中loading文字

方法

方法名参数默认值说明
_makeCode()生成二维码
_clearCode()清空二维码(清空二维码会触发result回调 返回值为空)
_saveCode()保存二维码到图库

事件

事件名返回值说明
result生成的图片base64或图片临时地址返回二维码路径 注:_clearCode()后返回空

2. 二维码卡片下载

使用插件xWxmlToCanvas,根据微信小程序wxml-to-canvas封装。

安装

npm i x-wxml-to-canvas -S

引入

实测引入node_modules内插件,条件编译时会走H5,而不是MP(小程序)。只有复制到项目内,才会走小程序。

import xWxmlToCanvas from './components/x-wxml-to-canvas/x-wxml-to-canvas';export default {    components: {xWxmlToCanvas}}

使用

属性

字段类型默认值描述
hideBooleanfalsecanvas是否在页面可见 true 通过fixed将canvas移至屏幕外
widthNumber300canvas宽度,单位px
heightNumber300canvas高度,单位px
xWxmlStringwxml 模板
xStyleObject{}样式
useCORSBooleantruecanvas 图片跨域

wxml 模板

  • 支持 viewtextimage 三种标签,通过 class 匹配 style 对象中的样式。

  • 文字必须用 text 标签包含,否则不显示。动态文字需要动态赋值宽高,否则会截断不显示。

const wxml = (projectName, inviteToChainStore, inviteExpiredTime, imgUrl) => `            ${projectName}                ${inviteToChainStore}                    ${inviteExpiredTime}            TP-LINK商云            `;

imgUrl 通过tki-qrcode组件获取。

样式

对象属性值为对应 wxml 标签的 class 驼峰形式。需为每个元素指定 width 和 height 属性,否则会导致布局错误。

存在多个 className 时,位置靠后的优先级更高,子元素会继承父级元素的可继承属性。

元素均为 flex 布局。left/top 等 仅在 absolute 定位下生效。

const style = (rowLength) => {    let textWidth = 212;    return {        "verticalCenter": {            display: 'flex',            flexDirection: 'column',            alignItems: 'center',            textAlign: 'center',        },        "inviteCard": {            width: 311, // 单位为 px            height: 518,            position: 'relative',            backgroundColor: '#fff',            borderRadius: 16,        },        "projectName": {            marginTop: 32,            fontSize: 16,            lineHeight: '1.2',            height: rowLength * 22,            width: textWidth,            fontWeight: 600,        }, ...    };};

方法

方法名描述返回值
renderToCanvas将wxml渲染至页面
canvasToTempFilePath将canvas转为图片地址 (H5端 Canvas 内绘制的图像需要支持跨域访问才能成功)promise函数,返回 图片地址,h5为base64
getCanvasImagerenderToCanvas 与 canvasToTempFilePath 合并promise函数,返回 图片地址,h5为base64
saveImageToPhotosAlbum图片保存至本地promise函数,返回 true / flase
this.$refs.xWxmlToCanvas.renderToCanvas().then(() => {    this.$refs.xWxmlToCanvas.canvasToTempFilePath().then(res => {        this.$refs.xWxmlToCanvas.saveImageToPhotosAlbum(res);    });});

真机调试不支持canvas type2d,可用预览模式。

3. 退出页面时拦截显示弹窗3.1 开启小程序页面返回询问对话框

watch: {    isChanged:{        handler: function(val) {            //#ifdef MP-WEIXIN            if (val) {                wx.enableAlertBeforeUnload({ // 只有真机会出现                    message: this.$t('pStoreInfo.quitConfirm')                });            } else {                wx.disableAlertBeforeUnload();            }            //#endif        },        immediate: true    }}

样式简单时可以使用。

3.2 微信小程序视图容器 page-container

“假页”容器组件,效果类似于 popup 弹出层,页面内存在该容器时,当用户进行返回操作,关闭该容器不关闭页面。

                 beforeleave() {} // 离开前触发

四、其他事项记录

  • 条目之类的有滚动条时和底部or底部按钮不一定有距离,但拉到底要有80rpx

  • 分页加载一般请求条数为10、20

  • 预览模式,在真机右上角三个点打开调试使用 vConsole

  • 页面在onLoad获取数据传递给组件,而组件在created生命周期使用该数据,有时会出现组件未获取到值的情况。