miniprogram-computed.js代码分析

miniprogram-computed.js代码分析

小程序本身不提供类似于Vue的计算属性,在再加上其渲染ui与js执行分离的原因,感觉要模拟一个计算属性处理起来有些困难,好在官方提供了我们自定义拓展miniprogram-computed
然后下文是对其中代码的一些个人理解,笔记。

如何在小程序的代码中,书写类似Vue这种的计算属性?

computed: {
	xxx() {
		return yyy
	}
}

没错,在小程序中也可以实现这种写法。就是通过其提供给我们的自定义组件功能:
Behavior(Object)
这个有点类似mixin,就是像注入式的在当前Component组件中执行自生的方法或者周期函数。通过

const computedBehavior = require('miniprogram-computed')
Component({
  behaviors: [computedBehavior],
})

注入到当前组件中,注意是定义为Component的组件,在Page组件中并不能使用。

代码分析

个人感觉代码可以分为 2个部分去理解
初始化computed属性----重写setData函数

初始化computed属性

behavior构造器中有个definitionFilter(defFields)函数会先执行。函数就是通过defFields参数来获取当前组件的上下文,也就是可以获取到我们写的computed属性,然后遍历computed中对象的键值对,插入到data属性中,也就是说computed中的对象,最终在标签中都是通过{{xx}}绑定我们的data属性(PS.代码中还有一段处理properties属性的,这里没有讨论)

definitionFilter(defFields) {
	const computed = defFields.computed || {}
	const computedKeys = Object.keys(computed)
	//...
	const needUpdate = {}
    const computedCache = scope._computedCache || scope.data  //  scope._computedCache 这里在生命周期声明
	for (let i = 0, len = computedKeys.length; i < len; i++) {
		const key = computedKeys[i]
	   	const getter = computed[key]
	   	if (typeof getter === 'function') { 
	    	const value = getter.call(scope)
	     	if (computedCache[key] !== value) { // 如果不同 就是需要通过setData更新的对象
	     		needUpdate[key] = value
	       		computedCache[key] = value
	     	}
	   	}
	}
	return needUpdate
}

这个needUpdate就是我们需要手动更新的属性

重写setData函数

在生命周期用一个对象保存原生的setData方法,然后用另外一个_setData来覆盖setData方法,使得在操作setData时(其实调用的是我们绑定的_setData方法),能同时更新到原生的data以及我们写上的computed字段。

lifetimes: {
    created() {
      this._originalSetData = this.setData
      this.setData = this._setData
    },
},
definitionFilter(defFields) {
	defFields.methods = defFields.methods || {}
    defFields.methods._setData = function (data, callback) {}
}

代码的思想是当我通过setData(覆盖了的)方法来更改了某个属性值。函数首先会去遍历所有data属性,然后挑出非computed的data属性,然后直接调用原生的setData(this._originalSetData )来首先更新data属性。 然后再通过判断所有的计算属性中有哪些属性是原来值不同,然后再更新渲染相关计算属性。两次渲染有先后顺序,先更新data再更新计算属性。

definitionFilter(defFields) {

	defFields.methods._setData = function (data, callback) {
		const dataKeys = Object.keys(data)
	      for (let i = 0, len = dataKeys.length; i < len; i++) {
	        const key = dataKeys[i]
	        if (computed[key]) delete data[key]
	    }
	
		// 做 data 属性的 setData
		originalSetData.call(this, data, callback)
		
		// 计算 computed
		const needUpdate = calcComputed(this)
		
		// 做 computed 属性的 setData
		originalSetData.call(this, needUpdate)
	}
}
后续

computed属性完成之后呢,下一步就是要自定义一个类似vuex的状态管理组件。网上的也有许多的版本,本人在老大的指导下去了解了一下redux以及mobx的状态管理机制。之后会继续与大家分享。

本人水平有限,有不对的地方,希望大家多多包涵。。。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值