原理:
小程序是没有watch功能的,所以我们要手动通过object.defineProperty()方法来实现
1.首先创建一个watch.js文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| // watch.js
const observe = (obj, key, watchFun, deep, page) => { let oldVal = obj[key] // 如果监听对象是object类型并且指定deep(深度监听) if (oldVal !== null && typeof oldVal === 'object' && deep) { // 递归子集,依次执行observe() Object.keys(oldVal).forEach(item => { observe(oldVal, item, watchFun, deep, page) }) } // 使用Object.defineProperty()劫持数据的写操作,在监听对象改变后执行传入的watchFun Object.defineProperty(obj, key, { configurable: true, enumerable: true, set(value) { if (value === oldVal) return watchFun.call(page, value, oldVal) oldVal = value }, get() { return oldVal } }) }
export const setWatch = (page) => { // 页面里的data字段 const data = page.data // 页面里的watch字段 const watch = page.watch // 对watch里列举的每一个字段(需要监听的字段)执行observe() Object.keys(watch).forEach(key => { let targetData = data const targetKey = key // 支持deep深度监听,使用deep时需要配合handler使用,否则直接编写函数 const watchFun = watch[key].handler || watch[key] const deep = watch[key].deep observe(targetData, targetKey, watchFun, deep, page) }) }
|
2.使用方式
在需要使用监听机制页面的js文件(如index.js)onLoad钩子里,执行setWatch(使用import关键词从watch.js引入),并传入当前页面实例this,完成初始化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { setWatch } from '../../watch.js'
Page({ data: { ... }, watch: { // 需要监听的字段 foo(val) { console.log('foo变化了,变化后的值是', val) ... // 具体操作 } }, // watch初始化,传入当前页面实例this onLoad() { setWatch(this) } })
|