当前位置: 首页 > news >正文

【JS Utils】Vue2 自定义计算属性 (兼容 uniapp 和 Vue 2.7 以前版本)

Vue2 自定义计算属性

  • 简述:类似 Vue 2.7 / Vue 3.x 的 computed 组合式API,可自由创建计算属性对象,灵活设置计算属性到Vue实例中。兼容 uniapp 环境和 Vue 2.7 以前版本下使用。

源码

/***  创建Vue计算属性对象*  @param  {Vue}             vm                    Vue实例*  @param  {Function|Object} getterOrOptions       取值方法或配置项*  @param  {Function}        getterOrOptions.get   取值方法*  @param  {Function}        getterOrOptions.set   设值方法*  @param  {Boolean}         getterOrOptions.cache 是否使用缓存 (默认是)*  @return {Object}*/
function createVueComputed(vm, getterOrOptions) {let Dep = createVueComputed.Dep ||= (vm._data || vm.$parent?._data)?.__ob__.dep.constructorlet Watcher = createVueComputed.Watcher ||= (vm._watcher || vm.$parent?._watcher)?.constructorif (!Dep || !Watcher) throw new Error('Cannot find necessary dependency methods.')let noop = createVueComputed.noop ||= function () {}let isFn = typeof getterOrOptions == 'function'let getter = isFn ? getterOrOptions : getterOrOptions.getlet setter = isFn ? void 0 : getterOrOptions.setlet cache = getter ? isFn || (getterOrOptions.cache ?? true) : falselet watcher = new Watcher(vm, getter || noop, noop, { lazy: true })return Object.defineProperties(Object.create(null), {value: {configurable: true,enumerable: true,set: setter ? setter.bind(null) : noop,get: cache ? function () {if (watcher.dirty) watcher.evaluate()if (Dep.target) {Dep.target.onTrack && Dep.target.onTrack({effect: Dep.target,target: this,type: 'get',key: 'value'})watcher.depend()}return watcher.value} : getter || noop},effect: { configurable: true, enumerable: true, value: watcher },__v_isRef: { configurable: true, value: true },__v_isReadonly: { configurable: true, value: !setter }})
}/***  设置Vue实例的计算属性*  @param  {Vue}     vm          Vue实例*  @param  {Object}  properties  计算属性表 { [key]: { get(rawGet), set(newVal, rawSet), cache } }*/
function setVueInstanceComputed(vm, properties) {let noop = setVueInstanceComputed.noop ||= function () {}let getDesc = Object.getOwnPropertyDescriptorlet proto = Object.getPrototypeOf(vm)let watchers = vm._computedWatchers ||= Object.create(null)for (let key in properties) {let desc = getDesc(vm, key) || getDesc(proto, key) || {}let isFn = typeof properties[key] == 'function'let getter = isFn ? properties[key] : properties[key].getlet setter = isFn ? void 0 : properties[key].setlet cache = getter ? isFn || (properties[key].cache ?? true) : falselet rawGet = desc.get?.bind(vm), rawSet = desc.set?.bind(vm)let useGet = getter ? function () { return getter.call(this, rawGet) } : nooplet useSet = setter ? function (val) { setter.call(this, val, rawSet) } : nooplet ref = cache ? createVueComputed(vm, useGet) : nullif (watchers[key]) watchers[key].teardown(), delete watchers[key]if (cache) watchers[key] = ref.effectObject.defineProperty(vm, key, {configurable: desc.configurable ?? true,enumerable: desc.enumerable ?? true,set: useSet,get: cache ? getDesc(ref, 'value').get : useGet})}
}// 可绑定到Vue原型链中使用
Vue.prototype.$computed = function () {return createVueComputed(this, ...arguments)
}
Vue.prototype.$setComputed = function () {return setVueInstanceComputed(this, ...arguments)
}

使用示例

<template><div><div>Demo1: {{ demo1 }} <button @click="val1++">++</button></div><div>Demo2: {{ demo2 }} <button @click="demo2++">++</button></div><div>Demo3: <input type="text" v-model="val3" /></div><div>Bind new computed ref: {{ val4 ? val4.value : '' }}<div><button v-if="val4" @click="bindVal4">bind</button><button v-else @click="unbindVal4">unbind</button></div></div></div>
</template><script>
// 绑定方法到Vue原型链中 (可选)
Vue.prototype.$computed = function () {return createVueComputed(this, ...arguments)
}
Vue.prototype.$setComputed = function () {return setVueInstanceComputed(this, ...arguments)
}export default {data() {return {val1: 100,val2: 200,val3: 'test'}},created() {// 在 created 周期内且当前为根实例时 (this === this.$root),需嵌套在 this.$nextTick 下使用。// 在 created 周期内且当前不为根实例或 mounted 周期内,可同步执行。const initComputed = () => this.$setComputed({// 基本设置方式demo1() {let res = this.val1 + 1console.log(`val1 get: ${res}`)return res},// 带配置设置方式,与 computed 配置一致demo2: {cache: false,get() {let res = this.val2 + 2console.log(`val2 get: ${res}`)return res},set(newVal) {this.val2 = newValconsole.log(`val2 set: ${newVal}`)}},// 可以覆盖实例下原有的 data, props, computed, methods 内的属性val3: {// 第一参数为原来的取值方法get(rawGet) {let res = `x_${rawGet()}`console.log(`val3 get: ${res}`)return res},// 第一参数为设置的新值,第二参数为原来的设值方法set(newVal, rawSet) {rawSet((newVal = newVal.replace(/^x_/, '')))console.log(`val3 set: ${newVal}`)}}})this === this.$root ? this.$nextTick(initComputed) : initComputed()},methods: {bindVal4() {// 自由设置计算属性this.val4 = this.$computed(() => {let res = this.val1 + this.val2console.log(`val4 get: ${res}`)return res})},unbindVal4() {// 销毁设置的计算属性this.val4.effect.teardown()}}
}
</script>
http://www.dtcms.com/a/581364.html

相关文章:

  • React 16
  • 东莞网站建设技术支持南京网站建设 零云建站
  • wordpress通知站点360搜索品牌建设与管理提案
  • Python实现手写数字识别
  • 零成本体验云计算!阿贝云免费服务器深度测评
  • 如何在Mac上同步iPhone短信
  • 网站建设好后有些什么资料软件工程月薪一般多少
  • Fastapi 进阶一:Fastapi依赖注入机制详解
  • Java实用面试经验:接口编程概念与技巧总结
  • 在VMWare上搭建Flume集群
  • vue_day04
  • 深入浅出 SPA/MPA
  • 怎么增加网站的关键词库个人网站申请空间
  • (已发25年8月华为云、51CTO)数组编程:编程的基础数据结构!
  • 北京网站制作设计哪个公司好网站开发人员结构配比
  • 面对未来:企业决策与适应力
  • bat 批处理实现 FFmpeg 命令压缩 MP4
  • openEuler 云原生实战:部署高性能 Redis 集群与压测分析
  • 机器学习-逻辑回归与二分类
  • 老玩家流失?基于数据驱动的游戏用户流失分析与干预策略
  • 做网站的公司名字北京注册网站
  • 如何用c 做网站hao123从网上开始
  • ThinkPHP 8 多应用模式下如何隐藏路由中的应用名
  • [SEO]网站不收录的原因及解决方法有哪些
  • conda以及Jupyter notebook的使用
  • 告别手动录入:文档抽取技术如何让RPA处理非结构化数据?
  • MIT-数字棋盘和数字三角形
  • 自助网站建设费用怎样做软件开发
  • Python面向对象和方法
  • AJAX 实例详解