爬坑记录--关于在小程序上实现watch监听数据变化

1,563 阅读2分钟

在写这篇文章之前,我要先感谢我们组的老大,没有他的帮助我无法独自解决这个问题

今天想在小程序上实现监听数据变化后进行一系列操作的功能,于是上网搜索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的用法,再此附上链接。