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} */functioncreateVueComputed(vm,getterOrOptions){letDepcreateVueComputed.Dep||(vm._data||vm.$parent?._data)?.__ob__.dep.constructorletWatchercreateVueComputed.Watcher||(vm._watcher||vm.$parent?._watcher)?.constructorif(!Dep||!Watcher)thrownewError(Cannot find necessary dependency methods.)letnoopcreateVueComputed.noop||function(){}let{get,set,cache}typeofgetterOrOptionsfunction?{get:getterOrOptions}:getterOrOptions cacheget?cache??true:falseletwatchernewWatcher(vm,get||noop,noop,{lazy:true})returnObject.defineProperties(Object.create(null),{value:{configurable:true,enumerable:true,set:set?set.bind(null):noop,get:cache?function(){if(watcher.dirty)watcher.evaluate()if(Dep.target){Dep.target.onTrackDep.target.onTrack({effect:Dep.target,target:this,type:get,key:value})watcher.depend()}returnwatcher.value}:get||noop},effect:{configurable:true,enumerable:true,value:watcher},__v_isRef:{configurable:true,value:true},__v_isReadonly:{configurable:true,value:!set}})}/** * 设置Vue计算属性 * param {Vue} vm Vue实例 * param {Object} data 设置的对象 * param {Object} props 计算属性表 { [key]: Function | { get(rawGet), set(newVal, rawSet), cache, configurable, enumerable } } * return {Object} 处理后的对象源 */functionsetVueComputeProps(vm,data,props){data||{}letnoopcreateVueComputed.noop||function(){}letgetDescObject.getOwnPropertyDescriptorletprotoObject.getPrototypeOf(data)letwatchersvmdata?vm._computedWatchers||Object.create(null):nullfor(letkeyinprops){let{get,set,cache,configurable,enumerable}typeofprops[key]function?{get:props[key]}:props[key]letdescgetDesc(data,key)||protogetDesc(proto,key)||{}cacheget?cache??true:falseconfigurable??desc.configurable??trueenumerable??desc.enumerable??trueletrawGetdesc.get?.bind(data),rawSetdesc.set?.bind(data)letuseGetget?function(){returnget.call(this,rawGet)}:noopletuseSetset?function(val){set.call(this,val,rawSet)}:noopletrefcache?createVueComputed(vm,useGet):nullif(watchers)watchers[key]?.teardown(),cache?(watchers[key]ref.effect):deletewatchers[key]Object.defineProperty(data,key,{configurable,enumerable,set:useSet,get:cache?getDesc(ref,value).get:useGet})}returndata}// 可绑定到Vue原型链中使用Vue.prototype.$computedfunction(){returncreateVueComputed(this,...arguments)}Vue.prototype.$setComputedfunction(){returnsetVueComputeProps(this,...arguments)}使用示例templatedivdivDemo1: {{ demo1 }}buttonclickval1/button/divdivDemo2: {{ demo2 }}buttonclickdemo2/button/divdivDemo3:inputtypetextv-modelval3//divdivBind new computed ref: {{ val4 ? val4.value : }}divbuttonv-ifval4clickbindVal4bind/buttonbuttonv-elseclickunbindVal4unbind/button/div/div/div/templatescript// 绑定方法到Vue原型链中 (可选)Vue.prototype.$computedfunction(){returncreateVueComputed(this,...arguments)}Vue.prototype.$setComputedfunction(){returnsetVueComputeProps(this,...arguments)}exportdefault{data(){return{val1:100,val2:200,val3:test}},created(){// 在 created 周期内且当前为根实例时 (this this.$root)需嵌套在 this.$nextTick 下使用。// 在 created 周期内且当前不为根实例或 mounted 周期内可同步执行。constinitComputed()this.$setComputed(this,{// 基本设置方式demo1(){letresthis.val11console.log(val1 get:${res})returnres},// 带配置设置方式与 computed 配置一致demo2:{cache:false,get(){letresthis.val22console.log(val2 get:${res})returnres},set(newVal){this.val2newVal console.log(val2 set:${newVal})}},// 可以覆盖实例下原有的 data, props, computed, methods 内的属性val3:{// 第一参数为原来的取值方法get(rawGet){letresx_${rawGet()}console.log(val3 get:${res})returnres},// 第一参数为设置的新值第二参数为原来的设值方法set(newVal,rawSet){rawSet((newValnewVal.replace(/^x_/,)))console.log(val3 set:${newVal})}}})thisthis.$root?this.$nextTick(initComputed):initComputed()},methods:{bindVal4(){// 自由设置计算属性this.val4this.$computed((){letresthis.val1this.val2 console.log(val4 get:${res})returnres})},unbindVal4(){// 销毁设置的计算属性this.val4.effect.teardown()}}}/script