简单实现个小程序计算属性 - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

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

知识

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

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

简单实现个小程序计算属性

发表时间:2021-2-22

发布人:葵宇科技

浏览次数:92

本来之前技术栈一直是Vue,后来做小程序了,各种不习惯,尤其是少了计算属性和监听器,wxml里面又不能直接放函数,又没有Vue那种过滤器的写法。也许有人说直接uni-app就好了,但是平时做跨端的很少,所以我偏不用uni-app,我就要自己写一个。以下内容纯靠个人臆想,搞出来的computed属性虽然能用,但仅供参考。

思路

出于偶然发现了小程序能够自己重写生命周期钩子,听说很多的一些统计sdk也都是利用这样的机制做事件打点统计啥的,于是这么好玩的东西,我决定参一脚试一下好不好玩。computed属性的扩展就是在重写的生命周期里面做的。

基本思路其实很简单,就是重写下setData用来监听修改的值,同步更新一下computed,为了让computed能够直接使用在wxml里就把computed上的属性全部挂在到data上去,更新也使用的setData更新。本人不善言辞,直接上,上再解释。

// computed.js
const oldPage = Page
Page = function (app) {
    let oldOnLoad = app.onLoad;
    app.onLoad = function (options) {
        // 存一下原来的setData
        let o_setData = http://www.wxapp-union.com/this.setData
        // 用于保存依赖
        let dep = {}
        // 重写setData
        this.setData = http://www.wxapp-union.com/function (o, fn) {
            // 调用原生setData
            o_setData.call(this, o, function () {
                // 如果定义有computed属性则判断一下是不是改变了计算属性中所依赖的变量
                if (app.computed) {
                    // 循环遍历
                    Object.keys(dep).map(c => {
                        Object.keys(o).map(i => {
                            // 找出需要触发更新的计算属性,兼容下几种写法
                            if (dep[c].includes(i) || dep[c].includes(i.split('.')[0]) || dep[c].includes(i.split('[')[0])) {
                                o_setData.call(this, {
                                    [c]: app.computed[c].call(this, this.data)
                                })
                            }
                        })
                    })
                }
                // 触发setData回调
                fn && fn.call(this)
            })
        }
        // 收集依赖,并将computed值挂载到data上
        if (app.computed) {
            // 为了不污染原来的data,深拷贝一份
            let _data = http://www.wxapp-union.com/JSON.parse(JSON.stringify(this.data))
            let bufferDep = []
            Object.keys(_data).map(key => {
                let val = _data[key]
                Object.defineProperty(_data, key, {
                    // 触发收集
                    get: function () {
                        bufferDep.push(key)
                        return val
                    }
                })
            })
            Object.keys(app.computed).map(key => {
                // 重置依赖
                bufferDep = []
                this.setData({
                    // 下面这里调一下computed将值挂载到data上,并且同时会触发收集
                    [key]: app.computed[key].call(this, _data)
                }, function () {
                    // 将每一个computed的依赖存好
                    dep[key] = bufferDep
                })
            })
        }
        oldOnLoad.call(this, options)
    }
    return oldPage(app)
}
复制代码

使用:

// app.js
require('./computed.js')
App({})
复制代码
// index.js
Page({
  data: {
    a: 0,
    k: [0, 0, 0, 1],
    c: {
      a: 9
    }
  },
  computed: {
    b(data) {
      return data.c.a + data.a + data.k[0]
    }
  },
  onLoad() {
    this.setData({
      a: 8,
      'c.a': 10,
      [`k[${0}]`]: 999
    }, () => {
      console.log(this.data.b)
    })
  },
})
复制代码

{{a}}
{{b}}
复制代码

显示结果如图:

小启发

其实小程序里面很多api都能重写或者使用defineProperty来监听,可以用来解决日常很多的开发问题,像啥页面栈问题,随手加个watch监听器,加个store全局数据管理啥的估计都不是啥大问题。重写页面各种生命周期啥的,只要不乱搞好像也没什么大问题。

相关案例查看更多