小程序入坑指南(1)——手写组件中watch监听方法

671 阅读2分钟

使用背景

在项目中遇到这样一种情况:pages中的组件A获取数据渲染页面后跳转到页面B,然后又回到页面A,此时需要重新刷新数据。

根据小程序page组件的生命周期来看,在show这个周期里面调用数据请求可以实现这个需求,但是此时我需要将请求的数据传给components组件中,并且刷新components内的数据,怎么办?

查看了一下components中组件的生命周期函数,发现没有可以做到上述需求的。想到了可以借鉴Vue中的watch方法和computed方法。通过监听传入的properties的属性值变化而做相应的操作。

分析watch的原理

本质上还是通过Object.defineProperty(obj,{...})中的getter和setter方法达到监听的效果,在setter中获取返回变化的新值并进行操作。

下面是我自己写的一个例子,pages组件传入components的数据变化通过计时器的方式动态的改变进行模拟。

目的是:监听传入值的变化而改变name的值,下面是主要文件及逻辑。

项目github地址

手写组件中watch监听方法

文件结构

|- 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);
  },
})