微信小程序(三)实现类似Vue中的 computed,watch 功能

前言

微信小程序和 vue 的语法非常像,会写 vue 的朋友上手 vue 基本是易如反掌。但是微信小程序中缺少了很多 vue 中没有的东西,比如计算属性 computed 、监听 watch。这些在平常开发中会经常用到。虽然微信小程序没有直接提供相关的 API 来使用这些,但是我们可以用其他的一些方法来简单的间接的实现这些功能。
这篇文章就是记录一下实现这些功能的过程和一些个人感受。

实现步骤

computed 的实现过程

computed 的实现过程非常简单,我们可以通过微信小程序脚本语言 WXS(WeiXin Script) 来简单实现类似vue中的 计算属性功能(computed)。

  1. 先理解官方文档的示例

    
    
    var msg = "hello world";
    
    module.exports.message = msg;
    
    
     {{m1.message}} 
    页面输出:hello world

我们可以把 标签当做一对 标签一样,我们可以在里面定义变量、函数。
然后在 “Mustache” 语法双括号里使用我们定义的函数和变量。

  1. 看完官方示例后我们就来实现一个类似 vue 中的简单的 computed
// page.js
Page({
  data: {
    order: {
        time: '2022-06-27',
        status: 1,
        amount: 10
    }
  }
})

  module.exports = {
    handleMatchStatus: function (source) {
      switch (source) {
        case 1:
          return '已支付'
        case 2:
          return '支付失败'
        case 3:
          return '退款中'
      }
    }
  }


 {{comp.handleMatchStatu(order.status)}} 
输出:已支付

在后台拿到的一些数据,比如订单数据里面只有商品单价和数据,页面需要你显示总价,这个时候就可以这种方式来实现;或者是项目中有些数据是状态或者类型数据,比如订单状态、订单类型、商品渠道等,通过后端传过来的都是数字,有字典表的话还好办,没有字典表的话一般都是和后端商量好,定死几个值,这个时候就可以通过这种方式显示数值对应的文字意思。

watch 的实现过程

首先明确实现后的效果:能监听小程序 page 里面 data 的所有属性值实时的变化。

思路:小伙伴们应该都知道 vue2.x 中的 双向绑定是通过 Object.defineProperty 方法来实现的。所以我们微信小程序可以借鉴这一方法。通过遍历 page 里 data 的属性,使用 Object.defineProperty 逐个的对每个属性进行监听,发现属性值被修改时就在 set 里调用对应的处理函数。

具体实现代码:

/**
 * 
 * @param {*} data 监听的对象
 * @param {*} watch 听的 key 和回调函数组成的类
 */
export const setWatcher = (data, watch, _this) => { // 接收 page 传过来的data对象和watch对象
  //监听属性 并执行监听函数
  const observe = (obj, key, watchFn) => {
    var val = obj[key]; // 为改变之前的属性值
    Object.defineProperty(obj, key, {
      configurable: true,
      enumerable: true,
      set: (value) => {
        val = value;
        watchFn.call(_this, value); // 调用对应函数
      },
      get: () => {
        return val;
      }
    })
  }
  Object.keys(watch).forEach(v => { // 将watch对象内的key遍历
    observe(data, v, watch[v]); // 监听data内的v属性,传入 watch 内对应函数以调用
  })
}

函数有三个入数 datawatch_this;

data 就是我们监听的对象,在小程序里也就是 page 里的 data

watch 就是一个对象,里面装着以键值对的形式储存的被监听的各个属性和对应的函数,key 是被监听属性,key 对应的值是这个属性值改变后的回调函数。

_this 是调用我们封装的这个函数的环境。

封装完后我们就可以在 page 页面导入并且使用了

import { setWatcher } from '../../utils/util'

Page({
  data: {
    a: 1,
    b: 2
  }
  async onLoad(options) {
    setWatcher(this.data, this.watch, this);
  },
  // 监听的值
  watch: {
    a: function (newValue) {
      // 值改变后的操作
      console.log(newValue)
    },
    b: function (newValue) {
      // 值改变后的操作
      console.log(newValue)
    }
  }
})

注意的地方

WXS

  • WXS 函数不能作为组件的事件回调
  • 在 WXS 中是不能调用其他js文件的函数和变量的,还有小程序的 API 也不能调用,因为 WXS 的运行环境是和其他 js 代码隔离的。有优点也有缺点吧,速度快,但是不能和其他文件的代码交互。

    watch

  • 封装的时候一定要用传进来的 this ,通过 call 修改 this 指向到函数被调用的词法环境。否则就调不了 set 中传进来的回调函数.

总结

  • 说 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。所以像这种订单流水中的一些数据用 WXS 简单实现的类似 vuecomputed 还是比较有优势,特别是这种要经常渲染到页面上的数据。
  • 上面代码中用 Object.defineProperty 这种方式封装实现的类似 vuewatch 的方式还有优化的地方,比如 data 中的深层数据改变时是监听不到的,还需深层次循环遍历。当然也可以借鉴 vue3 中用代理 proxy 的方式来实现。大家还有什么其他更好的方式可以在评论区留言,一起交流交流

写在最后

我是 AndyHu,目前暂时是一枚前端搬砖工程师。

文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注呀

未经许可禁止转载

speak less,do more.

你可能感兴趣的:(微信小程序(三)实现类似Vue中的 computed,watch 功能)