在写这篇文章之前,我要先感谢我们组的老大,没有他的帮助我无法独自解决这个问题
今天想在小程序上实现监听数据变化后进行一系列操作的功能,于是上网搜索watch的小程序实现方法。
普遍的解决方法是在app.js中构造监听器,然后再index.js中调用,这种方法虽然可以实现监听并且执行操作,但是无法修改this.data,而我又想在watch中修改data,于是死磕了一下午终于解决,写篇文章记录一下。
遇到的问题
本人原本的代码如下
// app.js
/**
* 小程序初始化
*/
onLaunch(){...}
/**
* 设置监听器
*/
setWatcher(data, watch) { // 接收index.js传过来的data对象和watch对象
Object.keys(watch).forEach(v => { // 将watch对象内的key遍历
this.observe(data, v, watch[v]); // 监听data内的v属性,传入watch内对应函数以调用
})
},
/**
* 监听属性 并执行监听函数
*/
observe(obj, key, watchFun) {
var val = obj[key]; // 给该属性设默认值
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
set: function(value) {
val = value;
watchFun(value,val); // 赋值(set)时,调用对应函数
},
get: function() {
return val;
}
})
}
//index.js
Page({
data: {
login: false,
avaUrl: "https://image.xiaomaiketang.com/xm/ax5iHhXZd4.png",
},
onLoad(){
var appInst = getApp();
appInst.setWatcher(this.data,this.watch)//设置监听器
},
watch:{
login:function(newValue){
if(newValue === true){
this.setData({avaUrl: "https://image.xiaomaiketang.com/xm/n288Rz8YST.png"})
}else{
this.setData({avaUrl: "https://image.xiaomaiketang.com/xm/ax5iHhXZd4.png"})
}
}
}
})
其中data里面login值的含义为是否登录,大致想实现的功能是根据是否登陆修改用户头像。
然而出现报错

大致就是watch调用中this的指向问题,watch中this未定义,所以无法修改this.data
解决
对app.js里监听器的监听属性中set处的watchFun函数使用call方法,并传入作用域,即可把原本的this传入watch中
代码如下
// app.js
/**
* 小程序初始化
*/
onLaunch(){...}
//监听器
setWatcher(data,watch,that){
Object.keys(watch).forEach(v =>{
this.observe(data, v, watch[v],that)
})
},
//监听属性
observe(obj, key, watchFun,that){
var val = obj[key]
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
set: function(value){
val = value
watchFun.call(that,value,obj)
},
get: function(){
return val
}
})
},
//index.js
Page({
data: {
login: false,
avaUrl: "https://image.xiaomaiketang.com/xm/ax5iHhXZd4.png",
},
onLoad(){
var appInst = getApp();
appInst.setWatcher(this.data,this.watch,this)//设置监听器
},
watch:{
login:function(newValue){
if(newValue === true){
this.setData({avaUrl: "https://image.xiaomaiketang.com/xm/n288Rz8YST.png"})
}else{
this.setData({avaUrl: "https://image.xiaomaiketang.com/xm/ax5iHhXZd4.png"})
}
}
}
})
总结
这次的问题主要为不熟悉Object.defineProperty()的数据结构,不了解call的用法,再此附上链接。