微信小程序
原理
微信小程序本质是一个单页面应用,主要开发语言是
JS、WXML、WXSS,小程序采用了双线程模型,逻辑层和渲染层,分别在两个线程中执行。渲染层的界面使用了
WebView进行渲染;逻辑层运行在JSCore线程内,没有DOM树和window对象。一个小程序存在多个界面,所以渲染层存在多个 WebView 线程,这两个线程的通信会经由微信客户端 Native 做中转,逻辑层发送网络请求也经由 Native 转发。
逻辑层用来处理业务逻辑、数据及调用接口,渲染层用来展现UI。通过
WeixinJSBridge实现与native通信。
双线程解决了传统浏览器中js执行时间过长,阻塞渲染的问题。
| 运行环境 | 逻辑层 | 渲染层 |
|---|---|---|
| iOS | JSCore | WKWebView |
| 安卓 | V8 | chromium定制内核 |
| 小程序开发者工具 | NWJS | Chrome WebView |
JSCore:是一套独立 JS 运行环境,是Native 与 JS 数据类型之间的转换桥梁,Bridge。常用于 OC 和 JS 代码之间的相互调用。
小程序优化方案
-
合理的分包,降低主包大小:主包只留Tab页(系统要求)、业务必要页面(错误兜底页、登陆授权页等),其余业务模块统统拆成分包
-
分包预加载:设置
preloadRule,框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。如:进入电商首页后,需要对商详和购物车等分包进行预加载。 -
组件异步分包:可以采用异步分包,可以将组件作为分包,在分包之间互相引用。
-
开启多线程 Worker:异步处理的任务,可以放置于 Worker 中运行,待运行结束后,再把结果返回到小程序主线程。worker目录下的所有文件会打包成一个js,可以打包到分包。
-
合并 setData 调用,降低通信频率。
-
与界面渲染无关的数据不要设置在data中。
-
图片优化:Android端可以全量使用webp格式。开启图片懒加载。静态图片使用CDN。
-
低端机降级:gif 动图进行降级成静态图片、JS、CSS 动画降级成静态样式。
小程序中数据怎么同步渲染
通过setData
setData工作原理:
小程序分为逻辑层和渲染层,而我们每次逻辑层改变了,要借由 Native 进行。小程序的渲染层和逻辑层由两个线程管理:渲染层的界面使用了 WebView 进行渲染;逻辑层采用 JsCore 线程运行 JS 脚本。一个小程序存在多个界面,所以渲染层存在多个 WebView 线程,这两个线程的通信会经由微信客户端 Native 做中转,逻辑层发送网络请求也经由 Native 转发。
所以我们不要多次 setData ,以及减少数据的传输量。我们的数据传输实际是一次 Javascript 脚本过程,当数据量过大时会增加脚本的编译执行时间,占用 WebView JS 线程。去除不必要的事件绑定( WXML 中的 bind 和 catch ),从而减少通信的数据量和次数。
1. 在渲染层把 WXML 转化成对应的 JS 对象。
2. 在逻辑层发生数据变更的时候,通过宿主环境提供的 setData 方法把数据从逻辑层传递到 Native,再转发到渲染层。
3. 经过对比前后差异,把差异应用在原来的 DOM 树上,更新界面。
生命周期
onLoad:首次进入页面加载时触发,可以在 onLoad 的参数中获取打开当前页面路径中的参数。onShow:加载完成后、后台切到前台或重新进入页面时触发onReady:页面首次渲染完成时触发onHide:从前台切到后台或进入其他页面触发onUnload:页面卸载时触发onPullDownRefresh:监听用户下拉动作onReachBottom:页面上拉触底事件的处理函数onShareAppMessage:用户点击右上角转发
onLaunch 和 onLoad 异步问题
通过Object.defineProperty解决
-
先创建一个全局变量
-
在 App.vue 创建一个 watch 函数通过Object.defineProperty监听全局变量的改变
-
在onLaunch里执行函数(如登录)执行完成后改变全局变量里的值
-
在其他页面js里调用app里的watch 监听着全局变量
-
全局变量一改变就继续往后执行页面上的函数
// App.vue内 监听id属性
watch: function (method) {
var obj = this.globalData; // 使用Object.defineProperty 监听this.globalData.id的变化
Object.defineProperty(obj, "id", {
configurable: true,
enumerable: true,
set: function (value) {
console.log(value, 'lxxxxxxxxx');
this._uid = value;
method(value); // 执行onLoad里要执行的函数
},
get: function () { return this._uid }
})
},
// A页面内onLoad
if (已登录) {
//正常执行登陆后的业务
return;
}
// 调用 App.vue 里的watch 方法
app.watch(function(id){
console.log("登陆流程已完成,新的id是:", id)
console.log('登陆流程已完成,新的app.globalData.id是:', app.globalData.id)
// 此处执行登陆后的业务
self.getData();
})
通过Promis解决
返回小程序内嵌H5,不刷新问题
内嵌H5只能用一个原生页承接<web-view> 组件,这个页面里onshow方法里去执行判断。可以判断当前url 和 返回再次进入时 的url 是否一直,如果一直则不变。不一致就替换bindUrl。
可以在 <web-view> 中的 bindUrl 加参数变成 http://xxx.com/xxx?flag=1
这样bindUrl变了,Web-View就会刷新。同时会新增一个webview,导致返回多次的问题。可以先将bindUrl=''置空,再去赋值。
小程序webview跳H5,返回需要返回两次问题
可以在H5中引入wxSDK,当点返回的时候H5监听卸载,主动触发navigateBack
window.onunload = function() {
wx.miniProgram.navigateBack({});
}
小程序webview与H5之间的通信方式
- 小程序->H5:通过URL拼接,一般用于传递登录
token。 - H5->小程序:通过wx.miniProgram.postMessage h5可以通过引入wxSDK提供的
wx.miniProgram.postMessage向小程序发送信息,同时<web-view>组件需要绑定bindmessage事件。缺点需要特定时机(后退,组件销毁,分享)才能向小程序发送信息。 - 长连-Websocket:优点:可以实现实时通信。缺点:成本高,服务器压力大等;放弃此方式。
调起小程序方案
- H5页面调起小程序:
-
通过 URL Scheme:需要自行开发中转H5页面,iOS系统直接识别 URL Scheme,可在短信等应用场景中直接通过Scheme跳转小程序。Android系统不识别 URL Scheme,需要在 H5 页面内使用location.href = 'weixin://dl/business/?t= TICKET'实现打开小程序。
-
微信内的H5可以通过
wx-open-launch-weapp开放标签打开小程序,提供一个可跳转指定小程序的按钮。使用此标签后,用户需在网页内点击标签按钮方可跳转小程序。<wx-open-launch-weapp id="launch-btn" appid="wx12345678" path="pages/home/index?user=123&action=abc" >
-
- 短信调起小程序:直接用微信的短链(URL Link),不需要开发H5。但是
https://wxaurl.cn/pFawq35qbfd这种短链在微信环境中打开只会跳【正式版】,即使你的env_version设定了【体验版】或【开发版】,需要在外部浏览器打开才能跳转指定的版本。 - APP直接调起小程序:开发者在微信开放平台账号下申请移动应用并通过审核后,即可获得移动应用拉起小程序功能权限。
uni-app
uni-app 是一个使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。
组件、api、与微信小程序一致。
hybrid框架+兼容APP端weex原生渲染。
uni-app 跨端原理
uni-app ,实现一套代码多端运行主要是 编译器和运行时(runtime) 这两部分配合完成的, 编译器将开发者的代码进行条件编译。