小程序宿主环境

1、渲染层和逻辑层

小程序的运行环境分成渲染层和逻辑层, WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。

1.1 渲染 “Hello world” 页面示例

WXML模板使用 view 标签,其子节点用 {{ }} 的语法绑定一个 msg 的变量。
渲染“Hello World”WXML脚本:

<view>{{ msg }}</view>

在 JS 脚本使用 this.setData 方法把 msg 字段设置成 “Hello World” 。
渲染“Hello World”JS脚本:

Page({
  onLoad: function () {
    this.setData({ msg: 'Hello World' })
  }
})

总结:
        1.渲染层和数据展示相关。
        2.逻辑层负责产生、处理数据。
        3.逻辑层通过 Page 实例的 setData 方法传递数据到渲染层。

1.2 通信模型

小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(下文中也会采用Native来代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发,小程序的通信模型如图所示。

 1.3 数据驱动

数据驱动:将状态和视图绑定在一起(状态变更时,视图也能自动变更)。

WXML结构和JS对象均可以表示一棵Dom树,如图所示。

WXML可以先转成JS对象,然后再渲染出真正的Dom树,回到“Hello World”那个例子,我们可以看到转换的过程如图所示:

通过 setData( ) 方法把msg数据从“Hello World”变成“Goodbye”,产生的JS对象对应的节点就会发生变化,此时可以对比前后两个JS对象得到变化的部分,然后把这个差异应用到原来的Dom树上,从而达到更新UI的目的,这就是“数据驱动”的原理,如图所示:

1.4 双线程下的界面渲染

小程序的逻辑层和渲染层是分开的两个线程。

在渲染层,宿主环境会把WXML转化成对应的JS对象;在逻辑层发生数据变更的时候,通过setData方法把数据从逻辑层传递到渲染层,再经过对比前后差异,把差异应用在原来的Dom树上,渲染出正确的UI界面,如图所示。

2、程序与页面

从逻辑组成来说,一个小程序是由多个“页面”组成的“程序”。

“小程序”指的是产品层面的程序(APP),而“程序”指的是代码层面的程序实例。

App构造器

App({
  onLaunch: function(options) {},
  onShow: function(options) {},
  onHide: function() {},
  onError: function(msg) {},
  globalData: 'I am global data'
})

App构造器的参数:

参数属性类型描述
onLaunchFunction当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
onShowFunction当小程序启动,或从后台进入前台显示,会触发 onShow
onHideFunction当小程序从前台进入后台,会触发 onHide
onErrorFunction当小程序发生脚本错误,或者 API 调用失败时,会触发 onError 并带上错误信息
其他字段  任意可以添加任意的函数或数据到 Object 参数中,在App实例回调用 this 可以访问

页面构造器Page( )

宿主环境提供了 Page() 构造器用来注册一个小程序页面,Page()在页面脚本page.js中调用,Page() 的调用方式如代码清单3-8所示。Page构造器接受一个Object参数,参数说明如表3-4所示,其中data属性是当前页面WXML模板中可以用来做数据绑定的初始数据,我们会在后文展开讨论;onLoad / onReady / onShow / onHide /onUnload 5个回调是Page实例的生命周期函数,我们在后文展开;onPullDownRefresh / onReachBottom / onShareAppMessage / onPageScroll 4个回调是页面的用户行为,我们也会在后文展开。
代码清单3-8 Page构造器

Page({
  data: { text: "This is page data." },
  onLoad: function(options) { },
  onReady: function() { },
  onShow: function() { },
  onHide: function() { },
  onUnload: function() { },
  onPullDownRefresh: function() { },
  onReachBottom: function() { },
  onShareAppMessage: function () { },
  onPageScroll: function() { }
})

Page构造器的参数:

参数属性类型描述
dataObject页面的初始数据
onLoadFunction生命周期函数--监听页面加载,触发时机早于onShow和onReady
onReadyFunction生命周期函数--监听页面初次渲染完成
onShowFunction生命周期函数--监听页面显示,触发事件早于onReady
onHideFunction生命周期函数--监听页面隐藏
onUnloadFunction生命周期函数--监听页面卸载
onPullDownRefreshFunction页面相关事件处理函数--监听用户下拉动作
onReachBottomFunction页面上拉触底事件的处理函数
onShareAppMessageFunction用户点击右上角转发
onPageScrollFunction页面滚动触发事件的处理函数
其他Any可以添加任意的函数或数据,在Page实例的其他函数中用 this 可以访问

3、组件

一个小程序页面可以分解成多个部分组成,组件就是小程序页面的基本组成单元。小程序的宿主环境提供了一系列基础组件。

组件是在WXML模板文件声明中使用的,WXML的语法和HTML语法相似,小程序使用标签名来引用一个组件,通常包含开始标签和结束标签,该标签的属性用来描述该组件。

示例:

<!-- page.wxml -->
<image mode="scaleToFill" src="img.png"></image>

需要注意,所有组件名和属性都是小写,多个单词会以英文横杠 "-" 进行连接。

所有组件都拥有下表列举的属性,主要涉及样式和事件绑定:

属性名类型描述其他说明
idString组件的唯一标示保持整个页面唯一
classString组件的样式类在对应的WXSS中定义的样式类
styleString组件的内联样式可以通过数据绑定进行动态设置的内联样式
hiddenBoolean组件是否显示所有组件默认显示
data-*Any自定义属性组件上触发的事件时,会发送给事件处理函数
bind / catchEventHandler事件

 各组件属性官方文档:

视图容器 | 微信开放文档 (qq.com)https://developers.weixin.qq.com/miniprogram/dev/component/#%E5%9C%B0%E5%9B%BE

4、API

wx对象是小程序的宿主环境所提供的全局对象,几乎所有小程序的API都挂载在wx对象底下(除了Page/App等特殊的构造器)。

小程序提供的API按照功能主要分为几大类:网络、媒体、文件、数据缓存、位置、设备、界面、界面节点信息,还有一些特殊的开放接口。

API一般调用的约定:

  • wx.on* 开头:监听某个事件发生
    • 接受一个 Callback 函数作为参数。当该事件触发时,会调用 Callback 函数。
  • wx.get* 开头:获取宿主环境数据。
  • wx.set* 开头:写入数据到宿主环境。
  • 如未特殊约定,多数 API 接口为异步接口 ,都接受一个Object作为参数。
  • API的Object参数一般由success、fail、complete三个回调来接收接口调用结果。

通过wx.request发起网络请求示例:

wx.request({
url: 'test.php',
data: {},
header: { 'content-type': 'application/json' },
success: function(res) {
 // 收到https服务成功后返回
 console.log(res.data)
},
fail: function() {
 // 发生网络错误等情况触发
},
complete: function() {
 // 成功或者失败后触发
}
})

API接口回调说明:

参数名字类型必填描述
successFunction接口调用成功的回调函数
failFunction接口调用失败的回调函数
completeFunction接口调用结束的回调函数(调用成功、失败都会执行)

 了解更多,请参见微信官方API文档:

基础 | 微信开放文档 (qq.com)https://developers.weixin.qq.com/miniprogram/dev/api/

5、事件

UI界面的程序需要和用户互动。在小程序里边,我们把“用户在渲染层的行为反馈”以及“组件的部分状态反馈”抽象为渲染层传递给逻辑层的“事件”,如图3所示。

事件处理示例:

<!-- page.wxml -->
<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>

// page.js
   Page({
  tapName: function(event) {
    console.log(event)
  }
})

事件是通过bindtap这个属性绑定在组件上的,同时在当前页面的Page构造器中定义对应的事件处理函数tapName,当用户点击该view区域时,达到触发条件生成事件tap,该事件处理函数tapName会被执行,同时还会收到一个事件对象event。

常见的事件类型:

类型触发条件
touchstart手指触摸动作开始
touchmove手指触摸后移动
touchcancel手指触摸动作被打断,如来电提醒,弹窗
touchend手指触摸动作结束
tap手指触摸后马上离开
longpress手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发
longtap手指触摸后,超过350ms再离开(推荐使用longpress事件代替)
transitionend会在 WXSS transition 或 wx.createAnimation 动画结束后触发
animationstart会在一个 WXSS animation 动画开始时触发
animationiteration会在一个 WXSS animation 一次迭代结束时触发
animationend会在一个 WXSS animation 动画完成时触发

 事件绑定

事件绑定的写法和组件属性一致,以key="value"的形式,其中:

  • key表示事件类型
    • 以bind或者catch开头,跟上事件的类型,如bindtap、catchtouchstart 。
    • bind 事件绑定 不会阻止冒泡事件向上冒泡,catch 事件绑定 阻止冒泡事件向上冒泡 。
    • 事件有冒泡阶段和捕获阶段

    • 自基础库版本1.5.0起,bind和catch后可以紧跟一个冒号,其含义不变,如bind:tap、catch:touchstart。

  • value是对应的函数名称,事件触发后执行该函数。

bind、capture-bind、catch、capture-catch:

(3条消息) 微信小程序事件之-bind、capture-bind、catch、capture-catch_lazy91的博客-CSDN博客https://blog.csdn.net/qq_59954212/article/details/124022229

6、兼容

小程序的宿主环境一直在迭代更新,提供更多的能力给开发者去完成更多的事情,所以你的小程序会运行在不同版本的宿主环境下。

我们可能需要针对不同手机进行程序上的兼容,此时可以使用 wx.getSystemInfo 或者 wx.getSystemInfoSync 来获取手机品牌、操作系统版本号、微信版本号以及小程序基础库版本号等,通过这个信息,我们可以针对不同平台做差异化的服务。

wx.getSystemInfoSync()
/*
  {
    brand: "iPhone",      // 手机品牌
    model: "iPhone 6",    // 手机型号
    platform: "ios",      // 客户端平台
    system: "iOS 9.3.4",  // 操作系统版本
    version: "6.5.23",    // 微信版本号
    SDKVersion: "1.7.0",  // 小程序基础库版本
    language: "zh_CN",    // 微信设置的语言
    pixelRatio: 2,        // 设备像素比
    screenWidth: 667,    // 屏幕宽度
    screenHeight: 375,     // 屏幕高度
    windowWidth: 667,    // 可使用窗口宽度
    windowHeight: 375,     // 可使用窗口高度
    fontSizeSetting: 16   // 用户字体大小设置
  }
 */

随着宿主环境的更新,新版本的宿主环境会提供一些新的API,你可以通过判断新的API是否存在来做程序上的兼容。

if (wx.openBluetoothAdapter) {
  wx.openBluetoothAdapter()
} else {
  // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
  wx.showModal({
    title: '提示',
    content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
  })
}

小程序还提供了wx.canIUse这个API,用于判断接口或者组件在当前宿主环境是否可用,其参数格式为: ${API}.${method}.${param}.${options}或者${component}.${attribute}.${option}
各个段的含义如下:

  • ${API} 代表 API 名字
  • ${method} 代表调用方式,有效值为return, success, object, callback
  • ${param} 代表参数或者返回值
  • ${options} 代表参数的可选值
  • ${component} 代表组件名字
  • ${attribute} 代表组件属性
  • ${option} 代表组件属性的可选值
    调用的示例代码如下。

    wx.canIUse调用示例代码:

    // 判断接口及其参数在宿主环境是否可用
    wx.canIUse('openBluetoothAdapter')
    wx.canIUse('getSystemInfoSync.return.screenWidth')
    wx.canIUse('getSystemInfo.success.screenWidth')
    wx.canIUse('showToast.object.image')
    wx.canIUse('onCompassChange.callback.direction')
    wx.canIUse('request.object.method.GET')
    
     // 判断组件及其属性在宿主环境是否可用
    wx.canIUse('contact-button')
    wx.canIUse('text.selectable')
    wx.canIUse('button.open-type.contact')
    

    我们可以选择合适的判断方法来做小程序的向前兼容,以保证我们的小程序在旧版本的微信客户端也能工作正常。在不得已的情况下(小程序强依赖某个新的API或者组件时),还可以通过在小程序管理后台设置“基础库最低版本设置”来达到不向前兼容的目的。例如你选择设置你的小程序只支持1.5.0版本以上的宿主环境,那么当运行着1.4.0版本宿主环境的微信用户打开你的小程序的时候,微信客户端会显示当前小程序不可用,并且提示用户应该去升级微信客户端。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值