Before writing this article, I would like to thank the boss of our group, without whose help I could not solve this problem alone

Today, I want to realize the function of monitoring data changes and performing a series of operations on the small program, so I searched the Internet for the implementation method of the watch small program.

The common solution is to construct listeners in app.js and then call them in index.js. Although this method can monitor and perform operations, it cannot modify this.data.

Problems encountered

My original code is as follows

// app.js
    /** * Small program initialization */onLaunch(){... }/** * sets the listener */
    setWatcher(data, watch) { // Receive the data object and watch object passed by index.js
        Object.keys(watch).forEach(v= > { // iterate over the key in the watch object
            this.observe(data, v, watch[v]); // Listen on the v property in data, pass in the corresponding function in watch to call})},/** * listen on the property and execute the listener function */
    observe(obj, key, watchFun) {
        var val = obj[key]; // Set the default value for this property
        Object.defineProperty(obj, key, {
            configurable: true.enumerable: true.set: function(value) {
                val = value;
                watchFun(value,val); // Call the corresponding function when assigning (set)
            },
            get: function() {
                returnval; }})}Copy the code
//index.js
Page({
    data: {
        login: false.avaUrl: "https://image.xiaomaiketang.com/xm/ax5iHhXZd4.png",
    },
    onLoad(){
        var appInst =  getApp();
        appInst.setWatcher(this.data,this.watch)// Set the listener
    },
    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"})}}}})Copy the code

In data, the meaning of the login value is whether to login, and the general function to achieve is to modify the user profile picture according to whether to login.

However, an error occurred

Basically, it is the pointing problem of this in the call of watch. This is not defined in watch, so this.data cannot be modified

To solve

To pass this into watch, call the watchFun function at set in app.js

The following code

// app.js
    /** * Small program initialization */onLaunch(){... }/ / listeners
  setWatcher(data,watch,that){
    Object.keys(watch).forEach(v= >{
      this.observe(data, v, watch[v],that)
    })
  },

  // Listen for attributes
  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
      }
    })
  },
Copy the code
//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)// Set the listener
    },
    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"})}}}})Copy the code

conclusion

I am not familiar with the data structure of Object.defineProperty() and I do not understand the use of call.

  • Object.defineProperty()

  • call()