在小程序中实现 watch - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 小程序相关 >

在小程序中实现 watch

发表时间:2021-1-11

发布人:葵宇科技

浏览次数:39

微信小程序官方没有提供 watch,用来监听 data 中的属性的变化

日常开发中如果少了 watch,会显得束手束脚

ES5 提供了 Object.defineProperty() 的方法,通过 getter/setter 劫持对象,实现在赋值时调用 setter 方法,执行 watch 中对应的方法,从而实现监听。

设置监听者

setWatcher 函数遍历会遍历 data 中的所有属性,给没有一个属性添加一个监听器 observe

const setWatcher = (page) => {
  const data = http://www.wxapp-union.com/page.data
  const watch = page.watch
  Object.keys(watch).forEach(key => {
    let targetData = http://www.wxapp-union.com/data
    const targetKey = key
    const watchFun = watch[key].handler || watch[key]
    const deep = watch[key].deep
    observe(targetData, targetKey, watchFun, deep, page)
  })
}
复制代码

实现监听器

observe 函数接收 5 个参数

  • paga 中的 data
  • data 中的属性 key
  • watch 中的函数
  • 是否要对 data 中的属性进行深度监听
  • page,会被传递到监听函数中

如果 deep 为 true 需要深度监听,递归调用 observe,实现深度监听

使用 Object.defineProperty 的 setter 方法拦截外部对 data 数据的处理,同时调用 watchFn 实现监听。

watchFn 接收两个参数,value 和 oldValue,使用 call 将 page 传递进去。使 watch 中可以正常使用 page(this)

/**
 * 
 * @param {Object} obj  // data
 * @param {String} key  // data 属性
 * @param {Fucntion} watchFun  // 监听函数
 * @param {Boolean} deep // 是否深度监听
 * @param {Object} page  // page 
 */
const observe = (obj, key, watchFn, deep, page) => {
  let oldVal = obj[key]
  if (oldVal !== null && typeof oldVal === 'object' && deep) {
    Object.keys(oldVal).forEach(item => {
      observe(oldVal, item, watchFun, deep, page)
    })
  }
  Object.defineProperty(obj, key, {
    configurable: true,
    enumerable: true,
    set(value) {
      if (value =http://www.wxapp-union.com/== oldVal) return
      watchFn.call(page, value, oldVal)
      oldVal = value
    },
    get() {
      return oldVal
    }
  })
}
复制代码

注意事项:

  • watch 只能监听已存在的属性,数组的 pop() 和 push() 等方法不会触发
  • 一开始不在 data 中的属性,后续动态添加的属性也不会触发

完整代码

const observe = (obj, key, watchFun, deep, page) => {
  let oldVal = obj[key]
  if (oldVal !== null && typeof oldVal === 'object' && deep) {
    Object.keys(oldVal).forEach(item => {
      observe(oldVal, item, watchFun, deep, page)
    })
  }
  Object.defineProperty(obj, key, {
    configurable: true,
    enumerable: true,
    set(value: any) {
	  if (value =http://www.wxapp-union.com/== oldVal) return
      watchFun.call(page, value, oldVal)
      oldVal = value
    },
    get() {
      return oldVal
    }
  })
}

export const setWatcher = (page) => {
  const data = http://www.wxapp-union.com/page.data
  const watch = page.watch
  Object.keys(watch).forEach(key => {
    let targetData = http://www.wxapp-union.com/data
    const targetKey = key
    const watchFun = watch[key].handler || watch[key]
    const deep = watch[key].deep
    observe(targetData, targetKey, watchFun, deep, page)
  })
}
复制代码

使用

import {  setWatcher} from "/utils/watch.js"

Page({
  data: {
    age: 12,
      person: {
        name: 'uccs'
      }
  },
  onLoad() {
    setWatcher(this)
  },
  watch: {
    age(val) {
      console.log(val)
    },
    person: {
      deep: true,
      handler(val) {
        console.log(val)
      }
    }
  },
  onClick() {
    this.data.age = 18
    this.data.person.name = 'tiantian'
  }
})
复制代码

相关案例查看更多