VUE中的proxy和defineproperty有何区别?
Admin 2021-10-18 群英技术资讯 899 次浏览
VUE中的proxy和defineproperty有何区别?proxy和defineproperty的区别有:Proxy可以劫持的数组的改变,defineProperty 需要变异、Proxy代理可以劫持对象的改变,defineProperty需要遍历、Proxy代理可以劫持对象属性的添加,defineProperty用this.$set来实现等等,下面我们详细的了解看看。
Proxy的出现,给vue响应式带来了极大的便利,比如可以直接劫持数组、对象的改变,可以直接添加对象属性,但是兼容性可能会有些问题
Proxy可以劫持的数组的改变,defineProperty 需要变异
defineProperty 中劫持数组变化的变异的方法
可以理解为在数组实例和原型之间,插入了一个新的原型的对象,这个原型方法实现了变异的方法,也就真正地拦截了数组原型上的方法
我们来看下vue2.x的源码
// vue 2.5.0 var arrayProto = Array.prototype; var arrayMethods = Object.create(arrayProto); // Array {} function def(obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); } var methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ]; /** * Intercept mutating methods and emit events */ methodsToPatch.forEach(function(method) { // cache original method var original = arrayProto[method]; // 比如 method是push,则结果为 // ƒ push() { [native code] } def(arrayMethods, method, function mutator() { var args = [], len = arguments.length; while (len--) args[len] = arguments[len]; var result = original.apply(this, args); var ob = this.__ob__; var inserted; switch (method) { case 'push': case 'unshift': inserted = args; break case 'splice': inserted = args.slice(2); break } if (inserted) { ob.observeArray(inserted); } // notify change ob.dep.notify(); return result }); }); /** * Observe a list of Array items. */ Observer.prototype.observeArray = function observeArray(items) { for (var i = 0, l = items.length; i < l; i++) { observe(items[i]); // 后续的逻辑 } };
Proxy可以直接劫持数组的改变
let proxy = new Proxy(fruit, { get: function (obj, prop) { return prop in obj ? obj[prop] : undefined }, set: function (obj, prop, newVal) { obj[prop] = newVal console.log("newVal", newVal) // 输出{ name: "lemon", num: 999 } return true; } }) proxy.push({ name: "lemon", num: 999 }) console.log(fruit)
Proxy代理可以劫持对象的改变,defineProperty需要遍历
defineProperty
let fruit = { "apple": 2, "pear": 22, "peach": 222 } Object.keys(fruit).forEach(function (key) { Object.defineProperty(fruit[i], key, { enumerable: true, configurable: true, get: function () { return val; }, set: function (newVal) { val = newVal; // 输出 newVal 888 console.log("newVal", newVal) } }) }) fruit.apple = 888
Proxy
let fruit = { "apple": 2, "pear": 22, "peach": 222 } let proxy = new Proxy(fruit, { get: function (obj, prop) { return prop in obj ? obj[prop] : undefined }, set: function (obj, prop, newVal) { obj[prop] = newVal console.log("newVal", newVal) // 输出 newVal 888 return true; } }) proxy.apple = 888
Proxy代理可以劫持对象属性的添加,defineProperty用this.$set来实现
defineProperty,如果属性不存在,则需要借助this.$set
<div id="app"> <span v-for="(value,name) in fruit">{{name}}:{{value}}个 </span> <button @click="add()">添加柠檬</button> </div> <script src="https://unpkg.com/vue"></script> <script> new Vue({ el: '#app', data() { return { fruit: { apple: 1, banana: 4, orange: 5 } } }, methods: { add() { this.fruit.lemon = 5; // 不会让视图发生变化 // this.$set(this.fruit,"lemon",5) // this.$set可以 } } }) </script>
Object.keys(fruit).forEach(function (key) { Object.defineProperty(fruit, key, { enumerable: true, configurable: true, get: function () { return val; }, set: function (newVal) { val = newVal; console.log("newVal", newVal) // 根本没有进去这里 } }) })
Proxy 直接可以添加属性
// vue 3 <div id="app"> <span v-for="(value,name) in fruit">{{name}}:{{value}}个 </span> <button @click="add()">添加柠檬</button> </div> <script src="https://unpkg.com/vue@next"></script> <script> Vue.createApp({ data() { return { fruit: { apple: 1, banana: 4, orange: 5 } } }, methods: { add() { this.fruit.lemon = 5; // 这样子是可以的 } } }).mount('#app') // vue 3 不再是使用el属性,而是使用mount </script>
let proxy = new Proxy(fruit, { get: function (obj, prop) { return prop in obj ? obj[prop] : undefined }, set: function (obj, prop, newVal) { obj[prop] = newVal console.log("newVal", newVal) // lemon, 888 return true; } }) proxy.lemon = 888
Proxy
其他属性
应用场景 promisify化
用Proxy写一个场景,请求都是通过回调,如果我们需要用promise包一层的话,则可以
// server.js // 假设这里都是回调 export const searchResultList = function (data, callback, errorCallback) { axios.post(url, data, callback, errorCallback) }
// promisify.js import * as server from './server.js' const promisify = (name,obj) => (option) => { return new Promise((resolve, reject) => { return obj[name]( option, resolve, reject, ) }) } const serverPromisify = new Proxy(server, { get (target,prop) { return promisify(prop, server) } }) export default serverPromisify
使用
// index.js import serverPromisify from './serverPromisify' serverPromisify.searchResultList(data).then(res=>{ })
如有不正确,望请指出
以上就是关于VUE中的proxy和defineproperty的区别介绍啦,上述示例具有一定的借鉴价值,有需要的朋友可以参考学习,希望对大家对大家学习proxy和defineproperty的使用有帮助,想要了解更多可以继续浏览群英网络其他相关的文章。
文本转载自脚本之家
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
本文依旧给大家分享Javascript设计模式的内容,这篇主要介绍Javascript适配器模式,那么究竟Javascript适配器模式是什么呢?有什么用?如何实现?接下来我们一一了解清楚。
相邻兄弟选择器是指在另一个元素之后可以选择的元素,两者具有相同的父元素。如需选择与另一元素紧密相连的元素,且两者具有相同的父元素,则可使用相邻兄弟选择器。
目录1. 自定义组件官方文档1.1 创建自定义组件1.1.1 声明组件1.1.2 编辑组件1.2 使用自定义组件1.3 页面向自定义组件传递数据(父传子)1.4 组件将事件传给页面(子传父)1. 自定义组件小程序允许我们使用自定义组件的方式来构建页面。官方文档自定义组件是不是用的微信的组件感觉很爽啊,如果不够用怎么办?
这篇文章主要为大家详细介绍了JS实现鼠标移动拖尾效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
这篇文章主要介绍了vue组件是如何解析及渲染的?,帮助大家更好的理解和使用vue,感兴趣的朋友可以了解下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008