🚀探索Vue3 Reactivity在小程序中的使用

917 阅读2分钟

天天水掘金,今天终于在掘金发表文章,大佬们请爱护我。

首先知道一点,Reactivity不是必须在Vue中才可以使用,所以才搞了起来,小程序中有更好的状态管理机制,该篇只为了探索。

1. 获取@vue/reactivity的源码

从哪里获取都可以,不要使用小程序的npm构建工具就行,会有问题。

image.png

2. 小程序app.js中导入该模块

复制源码到你自己定义的文件中,将模块导入后,为了方便使用,后期不想再其他页面中导入,把模块中的所有函数赋值给wx.d(不赋值给wx是可能会覆盖wx中的函数,但其实并不会,只是不想污染wx)

//app.js
import * as reactivity from './vendor/reactivity/reactivity.esm-browser.prod'

App({
  onLaunch: function () {
    this.initVueReactive()
  },

  initVueReactive() {
    console.log(Object.keys(reactivity))
    wx.d = {}
    Object.keys(reactivity).forEach(key => {
      wx.d[key] = reactivity[key]
    })
  }
})

编写shim.wx.d.ts文件,使用vscode/webstorm会有提示,因为只实验了以下三种功能,所以只有三个函数定义

declare namespace wx {
  namespace d {
    function reactive(options: any): void;
    function effect(callback: Function): void;
    function computed(callback: Function): any;
  }
}

在vscode中使用将会有提示

image.png

3. 编写一个简单的商品总价计算页面来测试(假装给Page添加了watch和computed🙄)

当我点击 加或者减 包邮不包邮,商品总价将会通过这些变量自动计算 小程序中Page函数是不包含计算和观察者属性的,使用Reactivity状态管理,可以让Page函数假装有了这些功能。

性能方面没有测试,不过简单的功能使用这个的话,感觉有点脱裤子放屁😂
image.png
image.png

wxml, json, wxss 代码就不展示了主要看下 js 文件

Page({

  /**
   * 页面的初始数据
   */
  data: {
    price: 1.2,
    number: 1,
    totalAmount: 0,
    postageAmount: 8,
    hasPostage: true,
    radioItems: [{
      value: 1,
      name: "包邮",
      checked: true,
    }, {
      value: 0,
      name: "不包邮"
    }]
  },

  onLoad: function (options) {
    // 绑定要管理的状态数据(这里把所有data的属性都进行了管理,感觉不是很好)
    this.state = wx.d.reactive(this.data)
    
    // 副作用 相当于vue 的 watch
    wx.d.effect(() => {
      // 因为effect中有使用状态管理中的属性,所以他们就勾搭起来了,副作用在此将会执行。
      // 计算属性
      this.state.totalAmount = wx.d.computed(() => {
        const postageAmount = this.state.hasPostage ? this.state.postageAmount : 0
        // 忽略这个toFixed(2)计算价钱,只是为了演示方便
        return (this.state.number * this.state.price + postageAmount).toFixed(2) 
      })

      // 给data绑定数据 对没错,还是要绑定
      this.setData({
        number: this.state.number,
        totalAmount: this.state.totalAmount,
      })
    })
  },

  // 增加数量
  onPressedNumberReduce() {
    if (this.state.number === 1) {
      return
    }
    this.state.number -= 1
  },

  // 减少数量
  onPressedNumberPlus() {
    this.state.number += 1
  },
	
  // 选择包邮或不包邮
  onRadioChange(evt) {
    this.state.hasPostage = evt.detail.value === "1"
  }
})

最后,感觉代码都集中在一起处理了,相对于以前没有那么的分散🙃

参考:

zhuanlan.zhihu.com/p/146097763
github.com/vuejs/vue-n…