123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /**
- * weapp custom component extend behavior -- computed
- * https://github.com/wechat-miniprogram/computed
- */
- import isEmpty from './isEmpty'
- import shallowEqual from './shallowEqual'
- module.exports = Behavior({
- lifetimes: {
- created () {
- this._computedCache = {}
- this._originalSetData = this.setData
- this.setData = this._setData
- this._doingSetData = false
- },
- },
- definitionFilter (defFields) {
- const computed = defFields.computed || {}
- const computedKeys = Object.keys(computed)
- // 计算 computed
- const calcComputed = (scope) => {
- const needUpdate = {}
- const computedCache = scope._computedCache || scope.data
- 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 (!shallowEqual(computedCache[key], value)) {
- needUpdate[key] = value
- computedCache[key] = value
- }
- }
- }
- return needUpdate
- }
- // 初始化 computed
- const initComputed = () => {
- defFields.data = defFields.data || {}
- // 先将 properties 里的字段写入到 data 中
- const data = defFields.data
- const properties = defFields.properties
- const hasOwnProperty = Object.prototype.hasOwnProperty
- if (properties) {
- // eslint-disable-next-line complexity
- Object.keys(properties).forEach((key) => {
- const value = properties[key]
- let oldObserver
- // eslint-disable-next-line max-len
- if (value === null || value === Number || value === String || value === Boolean || value === Object || value === Array) {
- properties[key] = {
- type: value,
- }
- } else if (typeof value === 'object') {
- if (hasOwnProperty.call(value, 'value')) {
- // 处理值
- data[key] = value.value
- }
- if (hasOwnProperty.call(value, 'observer')) {
- if (typeof value.observer === 'function') {
- oldObserver = value.observer
- } else if (typeof value.observer === 'string') {
- oldObserver = defFields.methods[value.observer]
- }
- }
- }
- // 追加 observer,用于监听变动
- properties[key].observer = function (...args) {
- const originalSetData = this._originalSetData
- if (this._doingSetData) {
- // eslint-disable-next-line no-console
- console.warn('can\'t call setData in computed getter function!')
- return
- }
- this._doingSetData = true
- // 计算 computed
- const needUpdate = calcComputed(this)
- // 做 computed 属性的 setData
- if (!isEmpty(needUpdate)) {
- originalSetData.call(this, needUpdate)
- }
- this._doingSetData = false
- if (oldObserver) oldObserver.apply(this, args)
- }
- })
- }
- // 计算 computed
- calcComputed(defFields, true)
- }
- initComputed()
- defFields.methods = defFields.methods || {}
- defFields.methods._setData = function (data, callback) {
- const originalSetData = this._originalSetData
- if (this._doingSetData) {
- // eslint-disable-next-line no-console
- console.warn('can\'t call setData in computed getter function!')
- return
- }
- this._doingSetData = true
- // TODO 过滤掉 data 中的 computed 字段
- 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
- if (!isEmpty(needUpdate)) {
- originalSetData.call(this, needUpdate)
- }
- this._doingSetData = false
- }
- },
- })
|