小程序

456 阅读7分钟

微信小程序

原理

微信小程序本质是一个单页面应用,主要开发语言是 JSWXMLWXSS,小程序采用了双线程模型逻辑层和渲染层,分别在两个线程中执行

渲染层的界面使用了 WebView 进行渲染;逻辑层运行在 JSCore 线程内,没有DOM树和window对象

一个小程序存在多个界面,所以渲染层存在多个 WebView 线程,这两个线程的通信会经由微信客户端 Native 做中转,逻辑层发送网络请求也经由 Native 转发。

逻辑层用来处理业务逻辑、数据及调用接口,渲染层用来展现UI。通过WeixinJSBridge实现与native通信

双线程解决了传统浏览器中js执行时间过长,阻塞渲染的问题。

运行环境逻辑层渲染层
iOSJSCoreWKWebView
安卓V8chromium定制内核
小程序开发者工具NWJSChrome 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 树上,更新界面。

生命周期

  1. onLoad:首次进入页面加载时触发,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
  2. onShow:加载完成后、后台切到前台或重新进入页面时触发
  3. onReady:页面首次渲染完成时触发
  4. onHide:从前台切到后台或进入其他页面触发
  5. onUnload:页面卸载时触发
  6. onPullDownRefresh:监听用户下拉动作
  7. onReachBottom:页面上拉触底事件的处理函数
  8. 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)  这两部分配合完成的, 编译器将开发者的代码进行条件编译。