likes
comments
collection
share

微信小程序(三十一)自定义watch监听属性

作者站长头像
站长
· 阅读数 20

微信小程序并没有为我们在普通的页面中提供类似vue中watch类似的监听属性。

还是那句话,人家没给,你还想用,自己定义一个。

监听器的原理,将data中需监听的属性写在watch对象中,并给其提供一个方法,当被监听属性的值改变时,调用该方法。

所以,我们需要用到Javascript中的Object.defineProperty()方法,来手动劫持对象的getter/setter,从而实现给对象赋值时(调用setter)执行watch对象中相对应的函数,达到监听效果。

Object.defineProperty()不在这里详细介绍,详情参照《深入浅出Object.defineProperty()

同样,VUE中的watch监听属性滥用会造成性能问题,我这里自定义的watch也是一样的,要适度使用。

一:自定义watch属性:

const observe = (obj, key, watchFun, deep, page) =>
{
  let val = obj[key];
  if (val != null && typeof val === "object" && deep)
  {
    Object.keys(val).forEach((item) => {
      observe(val, item, watchFun, deep, page);
    });
  }
 
  Object.defineProperty(obj, key, {
    configurable: true,
    enumerable: true,
    set: (value) =>
    {
      watchFun.call(page, value, val);
      val = value;
      if (deep)
      {
        observe(obj, key, watchFun, deep, page);
      }
    },
    get: () => {
      return val;
    }
  });
}
 
/**
 * @name: 自定义watch 监听属性
 * @author: camellia
 * @date: 2021-11-12
 */
const setWatcher = (page) =>
{
  let data = page.data;
  let watch = page.watch;
  Object.keys(watch).forEach((item) => {
    let targetData = data;
    let keys = item.split(".");
    for (let i = 0; i < keys.length - 1; i++)
    {
      targetData = targetData[keys[i]];
    }
    let targetKey = keys[keys.length - 1];
    let watchFun = watch[item].handler || watch[item];
    let deep = watch[item].deep;
    observe(targetData, targetKey, watchFun, deep, page);
  });
}
 
/**
 * 
// 引入自定义监听属性
const watch = require("../../utils/watch.js");
Page({
  data: {
    name: "时间里的"
  },
  onLoad() {
    watch.setWatcher(this);
  },
  watch: {
    name: function(newVal, oldVal) {
      console.log(newVal, oldVal);
    }
  }
});
 */
 
module.exports = {
  setWatcher
};

二:使用watch监听属性

1:文件存放位置

具体文件放在那里,这个纯看个人喜好,我在这里说一下我存放的位置仅供参考。

小程序根目录下的utils目录下:

微信小程序(三十一)自定义watch监听属性

2:调用:

(1):引入:

// 引入自定义监听属性
const watch = require("../../utils/watch.js");

(2):在onload中实例化监听函数

 onLoad() {
    watch.setWatcher(this);
  },

(3):调用watch监听属性:

  watch: {
    name: function(newVal, oldVal) {
      console.log(newVal, oldVal);
    }
  }

以下是完整的代码调用实例:

const watch = require("../../utils/watch.js");
Page({
  data: {
    name"时间里的"
  },
  onLoad() {
    watch.setWatcher(this);
  },
  watch: {
    namefunction(newVal, oldVal) {
      console.log(newVal, oldVal);
    }
  }
});

最后再强调一下,适度的调用watch属性。否则会造成性能问题

有好的建议,请在下方输入你的评论。

欢迎访问个人博客:guanchao.site

欢迎访问我的小程序:打开微信->发现->小程序->搜索“时间里的”