使用背景
在项目中遇到这样一种情况:pages中的组件A获取数据渲染页面后跳转到页面B,然后又回到页面A,此时需要重新刷新数据。
根据小程序page组件的生命周期来看,在show这个周期里面调用数据请求可以实现这个需求,但是此时我需要将请求的数据传给components组件中,并且刷新components内的数据,怎么办?
查看了一下components中组件的生命周期函数,发现没有可以做到上述需求的。想到了可以借鉴Vue中的watch方法和computed方法。通过监听传入的properties的属性值变化而做相应的操作。
分析watch的原理
本质上还是通过Object.defineProperty(obj,{...})中的getter和setter方法达到监听的效果,在setter中获取返回变化的新值并进行操作。
下面是我自己写的一个例子,pages组件传入components的数据变化通过计时器的方式动态的改变进行模拟。
目的是:监听传入值的变化而改变name的值,下面是主要文件及逻辑。
项目github地址
文件结构
|- components
|- demo //模块子组件,用来接收父组件传过来的数据并渲染
|- pages
|- index // 父组件页面,用来请求变化的数据
|- utils
|- utils.js // 封装watch的js文件
贴出主要代码
util.js文件
/** 模拟vue实现watch方法 */
const defineReactive = (data, key, val, fn) => {
Object.defineProperty(data, key, {
configurable: true,
enumerable: true,
get: function () {
return val
},
set: function (newVal) {
// if (newVal === val) return
if (isObjectValueEqual(newVal, val)) return
fn && fn(newVal)
val = newVal
},
})
}
const watch = (ctx, obj) => {
Object.keys(obj).forEach(key => {
defineReactive(ctx.data, key, ctx.data[key], function (value) {
obj[key].call(ctx, value)
})
})
}
demo.js文件
import { watch} from "../utils/util.js"
watch(this, {
number: function (newNum) {
let name = "";
if (newNum < 4){
name = "张三";
} else if (newNum < 8){
name = "李四";
} else {
name = "王二麻子";
}
this.setData({
name
})
},
newObj: function (newVal) {
console.log("newVal=====", newVal);
},
})