小程序/宿主环境

微信给小程序提供的环境成为宿主环境,我个人理解(不一定对,对宿主环境的真正理解我觉得需要知道小程序的详细框架原理以及和微信APP之间的联系):宿主环境包括了两大线程以及其他的一些代码(比如API定义函数、将小程序代码包注入宿主环境的代码等等)
通信模型 小程序/宿主环境
文章图片

Native是微信客户端,逻辑层和渲染层是通过两个线程来管理,每个页面对应一个webView线程。
数据驱动: 类似于react和vue,只要改变数据,页面就会自动更新视图。
渲染层将wxml先转换成js对象,这个对象等价于一棵dom树,之后进行渲染,其中,逻辑层将数据通过Native发送给渲染层,通过比较差异再重新渲染差异的部分
问题:1:小程序既然不支持dom,那怎么处理得到的js对象呢,web是使用dom API来实现的,小程序怎么实现的呢?通过Native?
2:小程序求差是在哪个线程执行的?是webView吗?类似于react里的diff,是在setState()时执行render(),求出虚拟dom,然后进行diff比较,之后找到patch,再根据patch来更新真实的dom

APP和Pages:

  • APP:
宿主环境提供了App()构造器来注册一个程序App,要写在app.js里面:App({}),App实例是单例对象,其他页面可以使用getApp()来获取此对象,比如使用全局变量globalValue的时候。
App({})参数对象:
App({ onLaunch: function(options){},//小程序初始化完成后触发,只执行一次 onShow: function(options){},//后台切换到前台触发 onHide: function(){},//前台切换到后台触发 onError: function(msg){},//脚本错误或调用api失败触发 globalValue: {} //全局变量的存储位置 })

当用户第一次进入小程序时,微信客户端初始化宿主环境(逻辑层和渲染层的线程吧?)以及获取小程序代码包(网络或者本地缓存),将代码包注入到宿主环境,派发onLaunch事件,这时触发此函数。
当用户点击右上角小圆点或者按下home键关闭时,小程序没有被销毁,只是进入了后台状态,这时触发onHide函数。
同样的,再次进入小程序,由后台变为前台,会触发onShow函数。
我们注意到,前面的onLaunch和onShow函数里面有参数options,这个参数提供了用户打开小程序的相关信息说明,包括但不限于打开的path,携带的参数,打开的场景值,appid(特定场景值下)等等。
最新的场景值汇总
App全局变量:所有的脚本都跑在一个线程JSCore里面,可以使用单例对象getApp().globalValue来实现全局变量的管理。同时,由于都是在同一个线程,所以不同的页面若是写了setTimeout等函数,注意离开页面时手动清除掉。
  • 页面:
    一个页面由wxml\wxss\json\js组成,其中,wxml和js是必须存在的
    页面需要注册在app.json中的pages里面,第一个是首页
    页面构造器Page({}):
Page({ data: { },//需要和视图层绑定的数据 //以下是声明周期函数 onLoad: function(options){ },//监听页面加载(只执行1次) onShow: function(){ },//监听页面显示 onReady: function(){ },//监听初次渲染完成(1次) onHide: function(){ },//监听页面隐藏 onUnload: function(){ },//监听页面卸载 //以下是用户触发的函数 onPullDownRefresh: function() { },//下拉更新 onReachBottom: function() { },//上拉触底 onShareAppMessage: function () { },//分享 onPageScroll: function() { } //页面滚动 其他函数: function(){} })

onLoad:
当页面初次加载时,微信客户端会给页面派发onLoad事件,触发onLoad函数,这个函数在页面没有被销毁之前,只执行一次。这个函数有一个参数,这个参数是为了页面传递时传递参数用的。当其他页面传递到本页面时使用下面的代码:
wx.navigateTo({ url: ‘pages/detail/detail?id=1&other=abc’ })
那么在本页面就可以使用
onLoad:function(options){
console.log(options.id+""+options.other);
}

来获取传过来的参数,实际应用场景举例:“商品列表和商品详情页”
onShow:
页面开始显示时,onShow函数执行,一般从其他页面再返回小程序时,都会触发这个函数。
onReady:
渲染层渲染完成后,会执行onReady函数,这时逻辑层和渲染层就可以进行交互了。
onHide:
页面不可见时执行,一般场景是:wx.navigateTo和底部tab栏
onUnload:
页面被微信客户端回收后,销毁时执行,一般场景是:wx.navigateBack和wx.redirectTo
data:
data是绑定到视图层的数据,this.setData(object, function)将数据发送到渲染层,由于渲染层和逻辑层是两个线程,所以setData是异步的,后面的function是渲染成功后的回调函数。
每次只需要设置改变的数据就可以,宿主环境会自动将变化的数据合并。
tips:
(1)setData会带来两个线程的通信延迟,所以每次更新的数据量不要超过1024kB
(2)data里面的数据不要设置成undefined,因为没有定义的数据以及undefined数据不会被绑定到渲染层
页面的用户行为:
下拉刷新 onPullDownRefresh
监听用户下拉刷新事件,需要在app.json的window选项中或页面配置page.json中设置enablePullDownRefresh为true。当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新。
上拉触底 onReachBottom
监听用户上拉触底事件。可以在app.json的window选项中或页面配置page.json中设置触发距离onReachBottomDistance。在触发距离内滑动期间,本事件只会被触发一次。
页面滚动 onPageScroll
监听用户滑动页面事件,参数为 Object,包含 scrollTop 字段,表示页面在垂直方向已滚动的距离(单位px)。
用户转发 onShareAppMessage
只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮,在用户点击转发按钮的时候会调用,此事件需要return一个Object,包含title和path两个字段,用于自定义转发内容,
页面跳转和路由:
小程序页面栈:使用wx.navigateTo()可以将新的页面推入页面栈中,数组的最后一项是当前显示的页面,第一项是最底部的页面(一般是首页)。
最大层级: 10级
(1)只能打开or关闭非tabbar页面:wx.navigateTo()、wx.navigateBack()、wx.redirectTo()
(2)只能打开tabbar页面:wx.switchTab()
当调用wx.switchTab()时,会清空当前的页面栈(除了在tabbar里面定义的page,注意,是否被清除意味着生命周期函数下一次是否还会被执行),页面栈变为当前的tabbar的页面。tab页面初始化后不会被销毁。
(3)wx. reLaunch({ url: ‘pageH’ }) :重启小程序并打开pageH页面
小程序/宿主环境
文章图片

组件 详细的组件官方文档
标签名和属性名都是小写的
页面由组件组成
API 详细的api官方文档
宿主环境提供了很多API,可以方便地调起微信提供的能力。
wx是宿主环境提供的全局对象,所有的api都是其下面的方法。
类别:网络、媒体、文件、数据缓存、位置、设备、界面、界面节点信息还有一些特殊的开放接口。
tips:
(1)wx.on* :监听某个事件,事件触发会调用 Callback。
(2)多数 API 接口为异步接口 ,都接受一个Object作为参数.
(3)wx.get* 开头的API是获取宿主环境数据的接口。
(4)wx.set* 开头的API是写入数据到宿主环境的接口。
(5)若拉起微信原生界面,会触发onHide事件;返回小程序界面后,会触发onShow事件。
事件: 用户行为和组件状态的反馈 抽象为 渲染层传给逻辑层的“事件”
通过Native来传递事件,有事件类型和事件对象。
事件类型:小程序/宿主环境
文章图片

事件对象:
小程序/宿主环境
文章图片

target是实际触发事件的组件,currentTarget是wxml中绑定了事件的组件。
事件绑定和捕获冒泡:
在组件上写bind*\capture-bind或者catch\capture-catch*就可以进行绑定事件,带有capture-表示在捕获阶段执行。catch可以中断捕获以及阻止冒泡,bind不会阻止冒泡。
除了上述事件类型之外,没有特殊声明,其他的组件自定义事件基本都是非冒泡事件,比如form的submit事件、input的input事件、scroll-view的scroll事件等等。
兼容: 由于小程序的宿主环境不断在迭代更新(为了给开发者提供更多的功能啦~),所以为了使小程序的代码能运行在不同的宿主环境中,就要做兼容的处理。
机型不同:
wx.getSystemInfo()或者wx.getSystemInfoSync()
api是否存在:
if (wx.openBluetoothAdapter) { wx.openBluetoothAdapter() } else { // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示 wx.showModal({ title: '提示', content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。' }) }

或者使用wx.canIUse():
${API}.${method}.${param}.${options}或者${component}.${attribute}.${option} wx.canIUse('openBluetoothAdapter') wx.canIUse('getSystemInfoSync.return.screenWidth')

【小程序/宿主环境】管理后台设置:
通过“基础库最低版本设置”来控制小程序可以打开的最低版本,一旦不可以版本不符合条件,直接打不开小程序,适用于小程序内部存在强依赖组件或者API的情况。

    推荐阅读