您當前位置>首頁 » 新聞資(zī)訊 » 小程序相關(guān) >
在小程序中(zhōng)實現 watch
發表時間:2021-1-11
發布人:葵宇科技
浏覽次數:39
微信小程序官方沒有提供 watch,用來監聽 data 中(zhōng)的屬性的變化
日常開發中(zhōng)如(rú)果少(shǎo)了 watch,會顯得束手束腳
ES5 提供了 Object.defineProperty() 的方法,通(tōng)過 getter/setter 劫持對象,實現在賦值時調用 setter 方法,執行 watch 中(zhōng)對應的方法,從而實現監聽。
設置監聽者
setWatcher 函數遍曆會遍曆 data 中(zhōng)的所有屬性,給沒有一個(gè)屬性添加一個(gè)監聽器(qì) observe
const setWatcher = (page) => {
const data = http://www.wxapp-union.com/page.data
const watch = page.watch
Object.keys(watch).forEach(key => {
let targetData = http://www.wxapp-union.com/data
const targetKey = key
const watchFun = watch[key].handler || watch[key]
const deep = watch[key].deep
observe(targetData, targetKey, watchFun, deep, page)
})
}
複制代碼
實現監聽器(qì)
observe 函數接收 5 個(gè)參數
- paga 中(zhōng)的 data
- data 中(zhōng)的屬性 key
- watch 中(zhōng)的函數
- 是否要對 data 中(zhōng)的屬性進行深度監聽
- page,會被傳遞到監聽函數中(zhōng)
如(rú)果 deep 為 true 需要深度監聽,遞歸調用 observe,實現深度監聽
使用 Object.defineProperty 的 setter 方法攔截外部對 data 數據的處理,同時調用 watchFn 實現監聽。
watchFn 接收兩個(gè)參數,value 和(hé) oldValue,使用 call 将 page 傳遞進去。使 watch 中(zhōng)可(kě)以正常使用 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 =http://www.wxapp-union.com/== oldVal) return
watchFn.call(page, value, oldVal)
oldVal = value
},
get() {
return oldVal
}
})
}
複制代碼
注意事項:
- watch 隻能監聽已存在的屬性,數組的 pop() 和(hé) push() 等方法不會觸發
- 一開始不在 data 中(zhōng)的屬性,後續動(dòng)态添加的屬性也不會觸發
完整代碼
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 =http://www.wxapp-union.com/== oldVal) return
watchFun.call(page, value, oldVal)
oldVal = value
},
get() {
return oldVal
}
})
}
export const setWatcher = (page) => {
const data = http://www.wxapp-union.com/page.data
const watch = page.watch
Object.keys(watch).forEach(key => {
let targetData = http://www.wxapp-union.com/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'
}
})
複制代碼