微信小程序开发技巧
布置既好看又好用的 input
input 组件输入区如果不留 padding 不好看,留多留少又不好确定还可能影响外层容器,比较好的一种方式是 input 外层套一个 view,input 本身不设定padding,依靠外层 view 实现视觉效果如padding、background-color、border等
外层View
input组件
实际效果
设置 Page 中 data 某项或部分数据
this.setData({
'项名':值
})
this.setData({
name: 'xiaoming',
age: '6',
// 复杂字符串拼接的项名时,最外层套一个中括号
['centerNameDataList[' + index + '].checked']: true
})
流式布局下如何让 scroll-view 既充满空间又有自己的高度
很多功能需要 scroll-view 有高度才能实现,高度可以是固定值、vh、或百分比均可,比如 bindscrolltoupper、bindscrolltolower 等,没有高度,很多事件无法触发或实现。流式布局下组件很可能并没有被赋予具体数值,因此解决方式是给 scroll-view 外层套一个 view,让 page 高度固定比如100%,再使 view 填满(剩余)目标空间,这样只需设置 scroll-view 的高度为 100% 即充满父级 view 即可。
<view class="scroll">
<scroll-view></scroll-view>
</view>
page{ height: 100% }
.scroll{ flex:1, overflow: scroll }
scroll-view{ height: 100% }
带列表和固定按钮能滚动的页面布局
这种布局方式非常常见,通常是顶部或者底部是固定的按钮或其他组件,剩下区域是列表内容,要求是列表区域的内容是可滑动的而固定区域的组件是固定不动的。如下图:
顶部固定搜索框,底部固定按钮,中间需要能滚动甚至是动态增长的内容列表。一开始的时候用 scroll-view,想错了,其实并不方便,基本思路是将所有组件都直接放到 page 即可,这样与 page 本身的拉动事件也不会冲突,反而好控制。
页面的基础结构自上而下分为 5 个部分,分别是:
- 顶部固定的 topView,在这里是搜索框的最外层容器
- 与顶部固定 view 同高的占位空白 stake,原因是在固定布局下使得列表区的 top 直接无视了 topView 的高度而直接顶到了页面起始高度也就是 0,这样 topView 将遮住部分列表区,因此需要一个与 topView 相同高度的砖头占住位置,使列表区的 top 在视觉上依旧是从 topView 的 bottom 开始
- 列表区 list,高度是动态的,根据实际数据量依次顺序排列
- 与底部固定 view 同高的占位空白 stake,作用同顶部 stake
- 底部固定的 bottomView,在这里是底部按钮
结构正确了实现就很简单了,固定在页面上使用这样的设置
.fixed-top{
position: fixed;
top: 0;
margin-top: 0;
}
.fixed-bottom{
position: fixed;
bottom: 0;
margin-bottom: 0;
}
设置好 stake 的高度,固定组件最好有固定高度这样 stake 设置也不容易出错,否则还得动态计算
.stake{
min-height: var(--element-height-56)
}
设定好了固定部分,列表区高度就不用操心了,因为是动态的,就爱长长爱短短了,非常方便。
小心 var 赋值
方法内赋值时,如果直接将 var a=b,将可能引起 b 的改变。
const Apis = {
foo:{
url: '/app/path?name=tom'
}
}
onRequest: function(options){
var api = Apis.foo
if(options.age){
api.url = `${api.url}&age=${options.age}`
}
}
第一次执行 onRequest 时,假设 options.age = 10,那么 api 的最终结果是 /app/path?name=tom&age=10
,更改 options.age 的值再次执行,Apis.foo
的 url 保存了上次执行的结果,也就是它也变成了 /app/path?name=tom&age=10
,导致第二次执行 onRequest 后,api.url 将存在两个 age=xx,避免的方法是将 api 声明并赋值为新对象 {},新对象中的属性(值)可以来自于 Apis,避免使 api 直接等于另一个对象
var api = {
url: Apis.foo.url
}
debug断点调试
打开小程序开发工具,打开“调试器”,切换到Source页,在Page中找到当前要调试的JS,并在其上打上断点即可
用 WeUI Upload 组件选择、预览和上传图片
先在page.json文件中添加引用
"usingComponents": {
"mp-uploader": "weui-miniprogram/uploader/uploader",
"mp-cells": "weui-miniprogram/cells/cells",
"mp-cell": "weui-miniprogram/cell/cell"
}
在 wxml 中
<mp-uploader bindselect="onCertImageSelect" bindfail="uploadError" bindsuccess="uploadSuccess" select="{{selectFile}}"
upload="{{uploadFile}}" files="{{files}}" max-count="5" title="凭证上传" tips="" delete="true">
</mp-uploader>
事件顺序是 select
->bindselect
->upload
->bindsuccess
或bindfail
,如果 select
过滤函数返回 false,组件将中断,后续事件也不会触发,即本次动作结束。了解了其执行流程,就可以在 js 中分别实现对应的事件处理逻辑。真正上传文件的逻辑是在 upload
发生,其要求最终要返回一个 Promise 对象,且 Promise 中的 resolve 要传递一个含有 urls 数组元素的 object,即 resolve({ url:[] })
upload:function(files){
// files 即为待上传文件所组成的对象
// do upload file
return new Promise((resolve, reject)=>{
if( 全部完成 ){
resolve({
urls: [ 成功上传文件1,成功上传文件2]
})
}else{
reject('some error')
}
})
}
成功执行上传的文件(即被放在 urls 数组中的文件),组件将自动以正常方式显示,其它未成功会显示为 Loading 状态始终转圈圈不会停止也不会变成 error,如果 reject 则集体 error。Uploader 组件比较好的地方是所选文件不用强制在页面级变量统一保存,在 upload 之前,包括 upload 时,都可以通过参数访问到,预览时也不必手写代码,算是比较易用的。缺点是,官方文档不准,部分属性不知道有什么作用,比如 files,如果乱写反而会引起冲突。
引入 npm 组件
以 vant weapp 组件为例
首先,安装 nodejs,它内置 npm,多讨厌你说!默认安装后,在控制台输入 npm -v
如果出现版本号,说明安装&环境变量设置正常。可以将 npm 单独升级一下,非必须工作,命令是 npm install npm@latest -g
下一步,在控制台中(或者在微信开发工具自带的终端中,但需要微信开发工具在安装 npm 之后打开或重启,以便使 npm 全局命令生效)切换到当前工作路径下(这也是在开发环境中打开的意义,默认路径就在项目下),运行组件安装命令 npm i @vant/weapp -S --production
下一步,按照 vant weapp 官方快速上手的指示,依次完成修改 app.json、project.config.json、构建npm包三项工作。下面说一下这三项工作可能的坑:
- app.json 官方让去掉
"style":"v2"
,这不会影响js,但可能会影响默认组件的样式,而被修改成vant weapp 样式,所以也可以不去掉,只要通过测试确保所使用的组件工作正常即可 - project.config.json 中注意官方的文档提示,以及开发工具版本的影响,当前就是按照文档提示,将
"miniprogramNpmDistDir": "./"
而不是"miniprogramNpmDistDir": "./miniprogram/"
- 按官方文档执行构建npm命令,并勾选“使用npm模块”
下一步,即可在 page 中按需引入组件并使用,但由于都是UI组件,可能产生样式冲突,需多注意、多检查
vant weapp Uploader使用示例
首先完成引入 npm 组件的工作,在 page.json 声明对组件的引用
"usingComponents":{ "van-uploader":"@vant/weapp/uploader/index" }
在 wxml 文件中添加组件
<van-uploader file-list="{{ certFileList }}" accept="image" max-size="5242880" max-count="9" upload-text="上传凭证" image-fit="aspectFill" bind:after-read="onAfterRead" bind:delete="onDelete" bind:oversize="onOverSize" />
并依照文档实现各API。需要提到的是,第三方组件的“完成度”似乎都比原生 Uploader 要好,比如 van-uploader ,不仅预览没有问题,可控制项也清晰,更好的是默认文件要一个一个的选择而不是依次选择多个,这就避免了批量上传的尴尬,挺好。
发布体验
当一版基本定型后,可发布体验版小程序供特定体验人员进行测试,步骤如下:
- 清除所有缓存(非必需,但会减少一些莫名其妙问题)
- 编译
- 上传
- 小程序管理后台版本管理功能中,将本次版本设定为体验版
以下文件没有被打包上传
- 程序规定的非项目需要文件,比如
.ignore
- 修改一下扩展名,比如无扩展名的图片就不能被上传
实时日志
小程序很贴心的准备了日志能力 RealtimeLogManager,使用时仅需要调用已有方法即可,日志将自动上传到小程序管理后台,通过开发管理-运维中心-实时日志进行查看,虽然有诸多限制,但对于一般应用依然足够,普通需求你自己实现出来也最多和小程序结构类似还肯定没人家的好。日志默认保存7天,不能导出,仅手机端运行时可上传,开发工具可以调用但日志不会上传
var log = wx.getRealtimeLogManager()
// 为当前即将记录的内容添加一条过滤标签
log.addFilterMsg()
log.info(...args)
log.warn(...ars)
log.error(...args)