アプレットでウォッチを実現
3222 ワード
WeChatアプレットの公式はwatchを提供していません.dataの中の属性の変化をモニターします.
日常開発でウォッチがなくなったら、手足を縛るようになります.
ES 5は、Object.defineProperty()の方法を提供し、getter/setterハイジャックオブジェクトを通じて、賦課時にsetterメソッドを呼び出し、watchで対応する方法を実行することにより、傍受を実現する.
傍受者を設定する
setWatch関数は、dataのすべての属性を巡回します.一つの属性がないためにモニターを追加します.
observe関数は5つのパラメータを受信します. pagaのdata data中の属性key watchの関数 は、dataの属性を深度傍受するかどうか . pageは、傍受関数 に伝達される.
deepがtrueであれば、深度傍受が必要となり、再帰的にobserveを呼び出し、深度傍受を実現する.
Object.definePropertyのsetter方法を使って、外部のdataデータに対する処理をブロックし、同時にwatFnを呼び出して傍受を実現します.
watch Fnは二つのパラメータを受け取り、valueとoldValueはcallを使ってpageを伝えます.watchの中で正常にpage(this)を使うことができます. watchは既に存在している属性のみをモニターすることができ、配列のpop()やpush()などの方法はトリガされません. 最初はdataの属性ではなく、後続の動的に追加された属性もトリガされない.
完全コード
日常開発でウォッチがなくなったら、手足を縛るようになります.
ES 5は、Object.defineProperty()の方法を提供し、getter/setterハイジャックオブジェクトを通じて、賦課時にsetterメソッドを呼び出し、watchで対応する方法を実行することにより、傍受を実現する.
傍受者を設定する
setWatch関数は、dataのすべての属性を巡回します.一つの属性がないためにモニターを追加します.
const setWatcher = (page) => {
const data = page.data
const watch = page.watch
Object.keys(watch).forEach(key => {
let targetData = data
const targetKey = key
const watchFun = watch[key].handler || watch[key]
const deep = watch[key].deep
observe(targetData, targetKey, watchFun, deep, page)
})
}
モニターを実現observe関数は5つのパラメータを受信します.
deepがtrueであれば、深度傍受が必要となり、再帰的にobserveを呼び出し、深度傍受を実現する.
Object.definePropertyのsetter方法を使って、外部のdataデータに対する処理をブロックし、同時にwatFnを呼び出して傍受を実現します.
watch Fnは二つのパラメータを受け取り、valueとoldValueはcallを使ってpageを伝えます.watchの中で正常にpage(this)を使うことができます.
/**
*
* @param {Object} obj // data
* @param {String} key // data
* @param {Fucntion} watchFun //
* @param {Boolean} deep //
* @param {Object} page // page
*/
const observe = (obj, key, watchFn, deep, page) => {
let oldVal = obj[key]
if (oldVal !== null && typeof oldVal === 'object' && deep) {
Object.keys(oldVal).forEach(item => {
observe(oldVal, item, watchFun, deep, page)
})
}
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
set(value) {
if (value === oldVal) return
watchFn.call(page, value, oldVal)
oldVal = value
},
get() {
return oldVal
}
})
}
注意事項:完全コード
const observe = (obj, key, watchFun, deep, page) => {
let oldVal = obj[key]
if (oldVal !== null && typeof oldVal === 'object' && deep) {
Object.keys(oldVal).forEach(item => {
observe(oldVal, item, watchFun, deep, page)
})
}
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
set(value: any) {
if (value === oldVal) return
watchFun.call(page, value, oldVal)
oldVal = value
},
get() {
return oldVal
}
})
}
export const setWatcher = (page) => {
const data = page.data
const watch = page.watch
Object.keys(watch).forEach(key => {
let targetData = data
const targetKey = key
const watchFun = watch[key].handler || watch[key]
const deep = watch[key].deep
observe(targetData, targetKey, watchFun, deep, page)
})
}
使用import { setWatcher} from "/utils/watch.js"
Page({
data: {
age: 12,
person: {
name: 'uccs'
}
},
onLoad() {
setWatcher(this)
},
watch: {
age(val) {
console.log(val)
},
person: {
deep: true,
handler(val) {
console.log(val)
}
}
},
onClick() {
this.data.age = 18
this.data.person.name = 'tiantian'
}
})