• proxy的应用场景


    欢迎大家访问我的博客dreamITGirl,不要吝啬你们的小星星,点个star~ 有问题的话,你可以将问题在 GitHub问我.

    写在前面
    随着Vue3越来越被大家学习,关于Proxy的使用也是不断收到关注。ProxyObject.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实现的

    测试结果1

    问题二:Object.defineProperty无法监听到数组的变化

    测试结果2

    从上面的图片中我们可以看到修改数组中的值是可以的,但是不能被监听到,输出的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输出结果

    操作数组的时候也会监听到

    修改数组

    操作对象属性中是对象的时候也会监听到

    修改对象

    比较两者的区别

    通过上面的代码,我们不难看出来它们的区别,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。我看到网站上有其他博客写的一个案例,案例的需求是这样的,根据用户输入的身份证号码,将其所在省份、出生日期分别写在表单中的对应表格中。
    文章链接

    数据格式化

    数据格式化,相对来说好理解一些。当后台返回接口数据不是我们想要的格式时,我们可以通过修改设置成我们想要的格式。这里就不再举例了赘述了。

  • 相关阅读:
    MongoDB Http Interface
    从python2.7和python3.0的语法差异总结
    从python2.7和python3.0的语法差异总结
    MongoDB聚合aggregate
    MongoDB聚合aggregate
    Windows 有没有办法查看文件被哪个进程占用
    Windows 有没有办法查看文件被哪个进程占用
    开启mongodb 的web
    开启mongodb 的web
    MongoDB基本命令操作
  • 原文地址:https://www.cnblogs.com/bllx/p/15927938.html
Copyright © 2020-2023  润新知