一. 前言
- 本篇指南建议具有一定小程序开发经验或已学习小程序开发指南(基础篇)的开发者进行阅读。
- 学习本篇指南后,您可对智能小程序有更深的理解,并能对已有小程序进行性能和体验上的优化。
学习内容
❣️ 智能小程序视图层和逻辑层数据通信,使用 SJS 优化性能。
❣️ 如何实现智能小程序模块化。
❣️ 自定义组件进阶使用指南。
二. 事件系统
什么是事件
- 事件是视图层到逻辑层的通讯方式。
- 事件可以将用户的行为反馈到逻辑层进行处理。
- 事件可以绑定在组件上,当绑定的事件被触发,就会执行逻辑层中对应的事件处理函数。
- 事件对象可以携带额外信息,如
id
、dataset
、touches
。
1. 普通事件绑定
事件绑定的写法类似于组件的属性,如:
<view bind:tap="handleTap">
Click here!
</view>
如果用户点击这个 view
,则页面的 handleTap
会被调用。
事件绑定函数可以是一个数据绑定,如:
<view bind:tap="{{ handlerName }}">
Click here!
</view>
Page({
data: {
handlerName: "handleTap",
},
handleTap() {
console.log("click handleTap");
},
});
在此绑定中,事件同样会被触发。
2. 使用 SJS 函数响应事件
<!-- 注:绑定的 SJS 函数必须用 {{}} 括起来 -->
<sjs module="sjs" src="./test.sjs"></sjs>
<view id="tapTest" data-hi="WeChat" bind:tap="{{sjs.tapName}}"> Click me! </view>
// test.sjs 文件实现 tapName 函数
function tapName(event, ownerInstance) {
console.log("tap miniApp", JSON.stringify(event));
}
module.exports = {
tapName: tapName,
};
ownerInstance
包含一些方法,可以设置组件的样式和 class
。
👉 立即免费领取开发资源,体验涂鸦 MiniApp 小程序开发。
3. 绑定并阻止事件冒泡
除 bind
外,也可以用 catch
来绑定事件。与 bind
不同,catch
会阻止事件向上冒泡。
- 点击
inner view
,触发handleTap3
,handleTap2
。 - 点击
middle view
,触发handleTap2
。 - 点击
outer view
,触发handleTap1
。
<view id="outer" bind:tap="handleTap1">
outer view
<view id="middle" catch:tap="handleTap2">
middle view
<view id="inner" bind:tap="handleTap3">
inner view
</view>
</view>
</view>
更多详情,请查看 事件系统内容。
三. SJS
1. 背景
频繁的用户交互可能使小程序出现卡顿的现象。例如,页面有 2 个元素 A 和 B,用户在 A 上做 touchmove
手势,要求 B 也跟随移动,movable-view
就是一个典型的例子。1 次 touchmove
事件的响应过程为:
- a、
touchmove
事件从视图层(Webview
)抛到逻辑层(App Service
)。 - b、逻辑层(
App Service
)处理touchmove
事件,再通过setData
来改变 B 的位置。
1 次 touchmove
的响应需要经过 2 次的逻辑层和渲染层的通信以及 1 次渲染,因此,通信的耗时比较大。此外,setData
渲染也会阻塞其它脚本执行,导致整个用户交互的动画过程会有延迟。
2. 实现方案
SJS 的思路是减少通信的次数,让事件在视图层(Webview
)响应。小程序的框架分为视图层(Webview
)和逻辑层(App Service
)。这种分层的目的是管控,让开发者的代码只能运行在逻辑层(App Service
)。然而,SJS 思路必须要让开发者的代码运行在视图层(Webview
)。
3. 使用方法
TYML 定义事件:
<sjs module="test" src="./test.sjs"></sjs>
<view change:prop="{{test.propObserver}}" prop="{{propValue}}" bind:touchmove="{{test.touchmove}}"
class="movable"></view>
SJS 文件 test.sjs 里面定义并导出事件处理函数和属性,改变触发的函数:
// event:事件对象
// ownerInstance:表示的是触发事件的组件所在的组件的 ComponentDescriptor 实例,如果触发事件的组件是在页面内的,ownerInstance 表示的是页面实例
const touchmove = function (event, ownerInstance) {
console.log("log event", JSON.stringify(event));
};
// newValue:新值
// oldValue:旧值
// ownerInstance:表示的是触发事件的组件所在的组件的 ComponentDescriptor 实例,如果触发事件的组件是在页面内的,ownerInstance 表示的是页面实例
// instance:表示触发事件的组件的 ComponentDescriptor 实例
const propObserver = function (newValue, oldValue, ownerInstance, instance) {
console.log("prop observer", newValue, oldValue);
};
export default {
touchmove: touchmove,
propObserver: propObserver,
};
上面的 change:prop
(属性前面带 change:
前缀)是在 prop
属性被设置的时候触发 SJS 函数,值必须用 {{}} 括起来。类似 Component
定义的 properties
里面的 observer
属性,在 setData({propValue: newValue})
调用之后会触发。
更多详情,请参考 SJS 语法参考。
👉 立即免费领取开发资源,体验涂鸦 MiniApp 小程序开发。