大概这一年左右的时间,都在跟小程序相关的需求。从开发到上线,流程上会跟以往的 Web 开发有些不同。此前除了大学时的一次课设,其他时间未曾接触过小程序,算是从 0 开始吧。不过得益于 Uniapp 基于 Vue.js 的语法封装,除了小程序自己的 API 之外,语法学习成本几乎没有。
与H5相比,孰优孰劣
对比
- 运行环境
- 网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应;
- 在小程序中渲染层和逻辑层分别运行在不同的线程中。即 双线程模型。
- 开发差异
- 小程序原生写法很像前端框架中的 Vue,也是 MVVM 模式,但是写法上没有完全照抄,都可以用类似虚拟 DOM 的形式能保证你的数据变化自动响应到模板;
- 小程序里不能使用任何 window 下的属性和方法;
- 小程序不可以过虚拟 DOM 来操作 DOM,不能使用任何 DOM 和 BOM 相关API;
- 这是因为:小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的 DOM API 和 BOM API;
- 小程序提供了很多 SDK 方法,几乎涵盖了 APP 能赋予 H5 的所有能力;
- 小程序类似于离线包,只要用户访问过,就会把主包代码下载到本地。
- 维护成本
- 网页开发者需要面对各式的浏览器兼容 :如 PC 端需要面对 IE、Chrome、QQ浏览器等,在移动端需要面对 Safari、Chrome 以及 iOS、Android 系统中的各式 WebView,开发时只需要常用的编辑器和浏览器即可 ;
- 小程序开发过程中需要面对的是两大操作系统 iOS 和 Android 的 微信客户端 ,以及用于辅助开发的小程序开发者工具;小程序的 开发者需要经过申请小程序帐号、安装小程序开发者工具、配置项目 等等过程才可进行小程序开发。
开发前准备
账号相关权限
开发者和测试相关的权限需要在微信后台添加;权限分为项目成员和体验成员,都有数量限制。
一般将开发者添加为 项目成员 ,将测试人员或者 PM 添加为 体验成员 。
开发上手
相关文档
项目目录
一个小程序主体部分由三个文件组成,必须放在项目的根目录:
文件 | 必须 | 作用 |
---|---|---|
app.js | 是 | 小程序逻辑:调用小程序实例、小程序生命周期 hook |
app.json | 是 | 全局配置:决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等 |
app.wxss | 否 | 小程序公共样式表 |
project.config.json | 是 | 项目配置文件(如:appId、编译时配置、依赖等) |
相关概念
小程序运行机制
冷启动
如果用户首次打开,或小程序销毁后被用户再次打开,此时小程序需要重新加载启动,即冷启动。冷启动不保留上次的浏览场景,打开即直接进入首页(可以使用 restartStrategy
配置冷启动进入的页面)。
热启动
如果用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时小程序并未被销毁,只是从后台状态进入前台状态,这个过程就是热启动。热启动保留上次浏览的 path。
小程序更新机制
开发者在管理后台发布新版本的小程序之后,微信客户端会静默更新到新版本。但是无法立刻影响到所有现网用户,最差情况下,也在发布之后 24 小时之内下发新版本信息到用户。
如果需要马上应用最新版本,可以使用 wx.getUpdateManager API 进行处理。
- UpdateManager.applyUpdate():强制小程序重启并使用新版本,在小程序新版本下载完成后调用;
- UpdateManager.onCheckForUpdate():监听向微信后台请求检查更新结果事件。微信在小程序冷启动时自动检查更新,不需由开发者主动触发;
- UpdateManager.onUpdateReady():监听小程序有版本更新事件。客户端主动触发下载(无需开发者触发),下载成功后回调;
- UpdateManager.onUpdateFailed():监听小程序更新失败事件;
基础库
小程序的能力需要微信客户端来支撑,每一个基础库都只能在对应的客户端版本上运行,高版本的基础库无法兼容低版本的微信客户端。
参考:基础库版本分布
分包
某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。这样做可以优化小程序首次启动的下载时间,在多团队共同开发时可以更好的解耦协作。
在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。
目前小程序分包大小有以下限制:
- 整个小程序所有分包大小不超过 20M
- 单个分包/主包大小不能超过 2M
开发者通过在 app.json subpackages 字段声明项目分包结构:
写成 subPackages 也支持:
1 | { |
打包原则
- 声明 subpackages 后,将按 subpackages 配置路径进行打包,subpackages 配置路径外的目录将被打包到 app(主包)中 ;
- app(主包)也可以有自己的 pages(即最外层的 pages 字段);
- subpackage 的根目录不能是另外一个 subpackage 内的子目录;
- tabBar 页面必须在 app(主包)内。
引用原则
- packageA 无法 require packageB JS 文件,但可以 require app、自己 package 内的 JS 文件;
- packageA 无法 import packageB 的 template,但可以 require app、自己 package 内的 template;
- packageA 无法使用 packageB 的资源,但可以使用 app、自己 package 内的资源。
例如:nodemodules 包中引用的代码会打包到主包中,因为该文件路径在 subPages 之外。
鉴权登录
常用 API 及能力
常用事件如 Tap、longPress 参照:WXML的冒泡事件列表
getApp():获取全局的应用实例,全局数据可以在 App 中设置
1
2
3
4
5
6
7
8// app.js
App({
globalData: 1
})
// a.js
var app = getApp()
app.globalData++授权相关信息
- 获取用户手机号
- 需要将
<button>
组件 open-type 的值设置为 getPhoneNumber,当用户点击同意之后,可以通过 bindgetphonenumber 事件回调获取到微信服务器返回的加密数据;1
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
- 需要将
- wx.getSetting() 获取用户当前权限配置,常可以用来在调用某项系统功能时,查看用户是否授权(例如保存存图片到相册)
- wx.authorize() 向用户发起授权请求,调用后会立即弹窗询问用户是否同意授权小程序使用某项功能( 如果用户之前已经同意授权,则不会出现弹窗 )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// 下边这段代码就是上两个 API 的应用
wx.getSetting({
success: (res?: any) => {
// 判断是否已经授权
if (!res['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
// 存储图片
wx.saveImageToPhotosAlbum(...)
}
})
} else {
// 调起客户端小程序设置界面,返回用户设置的操作结果
wx.openSetting()
}
}
}) - 若想取消当前用户授权,可【点击小程序右上角三个点】->【设置】->【用户信息】里取消授权
- 获取用户手机号
生成小程序二维码
- wxacode.createQRCode:获取小程序二维码,适用于需要的码数量较少的业务场景。通过该接口生成的小程序码,永久有效,有数量限制;
小程序运行版本的区分
- __wxConfig.envVersion:会返回当前小程序运行版本
- develop - 开发版
- trial - 体验版
- release - 正式版
- 注:此方法没有在官方文档上注明,只是挂在在全局 this 下,使用时注意该对象是否存在。
- 客户端分享的小程序链接可以指定小程序版本,需要跟客户端同学提前约定好,例如:
- __wxConfig.envVersion:会返回当前小程序运行版本
与其他第三方应用进行交互
- 跳转第三方小程序:需要将被调用的第三方小程序的 AppId 加入到小程序项目白名单中,正式版只能打开正式版;
- wx.navigateToMiniProgram
- wx.navigateBackMiniProgram
- 小程序内关注公众号:
<official-account>
原生组件,只能关注与小程序主体相同的公众号(后台配置),且样式不允许自定义,使用场景受限(扫码);
- 小程序唤起 app:
- 直接唤起:否;
由 app 直接调起小程序,然后小程序可以通过操作再调起 app;从 app 分享出去的小程序,可以调起 app:需要将<button>
组件 open-type 的值设置为 launchApp,可通过 app-parameter 参数给 App 传参(详情)
(PS:App分享到小程序的参数,支持选择 正式版、体验版、开发板)- 2021.5.19 后,小程序不再支持唤起 App 的能力;
- 无法从小程序的 webview 组件中唤起 App,微信做了 Url Scheme 拦截;
- 小程序内 webview 访问 H5:
<web-view>
原生组件,个人类型的小程序暂不支持使用,需要在微信后台将域名加入白名单;- 在微信后台下载”校验文件“,并将校验文件上传至网站根目录,供小程序平台进行验证,验证通过了才能成功添加域名;
- 注:若要从 webview 打开的 H5 跳转回小程序原生页,则需要提前引入 wx-js-sdk,使用
wx.miniProgram.navigateTo
方法 (官方文档)
- 小程序内打开公众号文章:
- 使用
<web-view>
组件即可打开相关联的公众号文章,非关联的公众号则提示“无法打开图文消息”; - 在微信管理后台:设置 -> 关联设置 中可以看到“关联的公众号”,(需要到公众号中关联小程序)。
- 使用
- 跳转第三方小程序:需要将被调用的第三方小程序的 AppId 加入到小程序项目白名单中,正式版只能打开正式版;
第三方应用与小程序的交互
- APP 调起微信小程序(只能调用与当前APP相关联的小程序) 参考
- 在微信管理后台:设置 -> 关联设置 中可以看到“关联的移动应用”;
- 可跳转到指定页面
- 限制:
- APP和小程序相同主体:如果在同一个主体下,不存在调用个数限制;
- APP和小程序不同主体:如果不在同一个主体下,一个app最多只能关联3个小程序。也就是说,非相同主体的小程序最多拉起3个;
- 外部 H5 调起微信小程序
- 直接调用:否;
- 可根原生同学协商,使用 APP 提供的 SDK 方法调用;
- 或者使用使用微信云开发能力的托管 H5,免鉴权直接跳转任意合法的小程序;
- 短信跳转小程序
- 直接调用:否;
- 微信开放能力 - 服务端接口 - 可以获取打开小程序任意页面的 URL Link。适用于从短信、邮件、网页、微信中直接打开;
- 使用微信云开发能力,打开M页跳转小程序(待调研);
- 公众号打开小程序(只能调用与当前公众号相关联的小程序)参考
- APP 调起微信小程序(只能调用与当前APP相关联的小程序) 参考
常见的问题
- 微信小程序之 1rpx 的边框在部分机型上展示不全
- 小程序 tabbar 关联的页面,不可用用 navigateTo 进行跳转,只能使用 swtichTab 方法。
- 小程序原生组件样式覆盖不掉?
- 由于原生组件脱离在 WebView 渲染流程外,故层级是最高的,所以页面中的其他组件无论设置 z-index 为多少,都无法盖在原生组件上。
- 小程序内打开的微信公众号文章不支持二维码长按识别(公众号二维码除外),这是小程序在新版微信做的限制(详见:「微信7.0.23」版本中,出现小程序中内嵌的公众号文章里的二维码无法长按识别的问题?)
- 小程序内图片没有识别二维码的能力和相关的API(只可以识别小程序码)
- 测试时怎样关闭域名校验?
- 在小程序的右上角设置里,将程序置为调试状态即可。
项目测试
可以从 H5 直接进入小程序体验版
在移动端打开:
https://open.weixin.qq.com/sns/getexpappinfo?appid={AppId}&path={pagesPath}.html
即可访问小程序体验版,并跳转到对应路径(注意:此链接只能在移动端微信中打开).
也可以,通过判断微信版本,自己写一个测试/入口构造页面来作为测试入口。
缓存
小程序的所有缓存数据上线为 10MB,像 storage 中的数据,除非用户主动删除或因存储空间原因被系统清理,否则数据都一直可用。
清除缓存:
- 发现-小程序-在列表中删除掉测试的小程序;
- 微信-我-设置-通用-存储空间;
- 安卓在私信聊天页输入 debugx5.qq.com ,利用腾讯的工具清理 cookie;
- 退出登录,重新登录。
Android
由于安卓9的安全限制,无法信任用户自行安装的证书,正常状态连代理打开小程序会报错“获取运行环境失败”;
将手机 root 后,解决证书信任问题后才能访问。
IOS
直接连代理,访问小程序即可。
框架对比
业内知常见小程序框架:wepy、mpvue、uni-app、taro、chameleon。
主流框架对比:详情
主流框架性能对比:详情
目前使用的是 Uniapp,因为可以编译多平台的小程序,且与 Vue 的语法能无缝衔接,开发成本较低。
个人偏见
关于功能开发
从一个开发者的角度,我并不希望听到 PM 说“这个功能和页面要和APP保持一致”。
个人认为 APP 承载的功能是核心且重的,也是在用户体验上最优的一端,若将 H5 和小程序的功能完全与 APP 拉齐,不仅开发周期长,维护难度高,同时会让小程序和 H5 失去本身的轻量优势。
小程序 和 H5 应该承载更多引流的功能,而不是一整套完备的 APP,当然了,这句话是针对公司有核心 APP 的情况;若是主要产品就是小程序方向,就看功能利弊的权衡了,只是个人认为“小程序”不应该变成一个庞然大物,对于 PM 而言应该更侧重于对于不同端的用户给出不同的产品特性,而不是一味的追求“复刻”。
关于设计还原
由于小程序提供的通用的原生组件有的时候,是不允许开发者更改某些样式的,此时要跟设计同学及时反馈;若要自己开发某些组件,记得增加工期。
用现有的框架也可以:汇总9款优秀的开源小程序UI框架
关于部署上线
最后一点,不管是开发还是审核部署,小程序强烈依赖微信运行环境,被封禁和能否上线的话语权(例如小程序中有游戏广告之类的,通常就会被封禁)并非掌握在自己手里,需要做好被封禁时的准备,域名同理。