proxy的应用场景
欢迎大家访问我的博客dreamITGirl,不要吝啬你们的小星星,点个star~ 有问题的话,你可以将问题在 GitHub问我.
写在前面
随着Vue3越来越被大家学习,关于Proxy的使用也是不断收到关注。Proxy
和Object.defineProperty
的对比也备受关注。这篇文章适合有vue开发经验的同学阅读。
回顾Object.defineProperty
在vue2.x版本中,是通过Object.defineProperty
进行双向数据绑定的,接下来看一下Object.defineProperty
是如何进行双向绑定的。接下来简单实现一下。
function observe(obj) { if (typeof obj === 'object' ) { for (const key in obj) { defineReactive(obj,key,obj[key]) } } } function defineReactive(obj,key,value) { // 针对value是对象,进行递归 observe(value) Object.defineProperty(obj,key,{ get:function () { console.log(`获取${key}:value是${value}`) return value }, set:function (v) { observe(v) console.log(`${key}数据改变了`) value = v } }) } let obj = { name: '守候', flag: { book: { name: 'js', page: 325 }, interest: ['火锅', '旅游'], } } observe(obj)
问题一:Object.defineProperty
无法监听增加或删除的属性
我们知道Object.defineProperty
无法监听增加或者删除的属性,
在我们使用vue2.x中,增加属性我们一般会通过$set
的方法进行操作,$set
内部也是通过使用Object.defineProperty
实现的
问题二:Object.defineProperty
无法监听到数组的变化
从上面的图片中我们可以看到修改数组中的值是可以的,但是不能被监听到,输出的interest数组还是改之前的数组
问题三:如果对象的层级很多的情况下,不断的递归,会导致时间过长,影响性能
回顾Proxy
vue3的版本中,采用了Proxy
的方式。MDN 中的定义如下:
对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)
简单来说就是,对目标对象设置一层拦截,任何对这个对象的操作都会经常这层拦截。这就相当于Axios的拦截器。
接下来写个案例,理解一下Proxy
function observerProxy(obj) { let handler = { get(target, key, receiver) { console.log('获取:' + key) // 如果是对象,就递归添加 proxy 拦截 if (typeof target[key] === 'object' && target[key] !== null) { return new Proxy(target[key], handler) } return Reflect.get(target, key, receiver) }, set(target, key, value, receiver) { console.log(key + "-数据改变了") return Reflect.set(target, key, value, receiver) } } return new Proxy(obj, handler) } let obj = { name: '守候', flag: { book: { name: 'js', page: 325 }, interest: ['火锅', '旅游'], } } let objTest = observerProxy(obj)
操作数组的时候也会监听到
操作对象属性中是对象的时候也会监听到
比较两者的区别
通过上面的代码,我们不难看出来它们的区别,proxy
还是很强大的,有11种方法。能够处理Object.defineProperty
这个方法中无法处理的。
Proxy的处理场景
负索引数组
在使用splice(-1)
和 slice(-1)
等API的时候,当输入的是负数时,会自动定位到数组的尾部最后一项,但是在普通的数组中,负数是不能用的。
let arr = [1,2,3] console.log(arr.splice(-1)) // [3] console.log(arr[-1]) // undefined
这种情况下我们可以通过创建一个proxy
对象,进行控制返回值
function arrProxy(params) { let handler = { get(target,key){ if (target instanceof Array && target.length > 0) { if (key > 0) { return target[key] } else { let len = target.length if (key * -1 > len) { return new Error('该下标不存在') } let index = len + Number(key) // key是字符串 return target[index] } } else if (typeof target === 'object' && target !== null) { console.log('这是一个对象') return target[key] } } } return new Proxy(params,handler) } let arr = [1,2,3,4,5,6] let testArr = arrProxy(arr) console.log(testArr[-1]) // 6
表单校验
在对于表单的验证上,当用户修改表单中的数据时,可通过proxy
进行设置拦截。
举个例子:
function validFrom(formObj) { let handler = { set(target,key,value){ if (key === 'age') { console.log('here',value > 10 && value < 40,typeof value == 'number' ) if (typeof value == 'number' && (value > 10 && value < 40)) { target[key] = value } else { console.log('出现错误') throw new Error('请输入准确的值') } } } } return new Proxy(formObj,handler) } let form = { name:'Alice', age:20 } let testForm = validFrom(form) testArr.age = 60 // '请输入准确的值'
根据用户输入值,解析存储
比如有一个需求,根据用户输入的值,将其解析分成对应属性的值。这样的话可以使用proxy。我看到网站上有其他博客写的一个案例,案例的需求是这样的,根据用户输入的身份证号码,将其所在省份、出生日期分别写在表单中的对应表格中。
文章链接
数据格式化
数据格式化,相对来说好理解一些。当后台返回接口数据不是我们想要的格式时,我们可以通过修改设置成我们想要的格式。这里就不再举例了赘述了。
本文来自博客园,作者:前端加油站,转载请注明原文链接:https://www.cnblogs.com/bllx/p/15927938.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?