1. 程式人生 > 其它 >vue3為什麼要用proxy實現雙向資料繫結?

vue3為什麼要用proxy實現雙向資料繫結?

一:object.defineProperty的缺點:

1.因為es5的object.defineProperty無法監聽物件屬性的刪除和新增
2.不能監聽陣列的變化,除了push/pop/shift/unshift/splice/spObject.definert/reverse,其他都不行
3.Object.defineProperty只能遍歷物件屬性直接修改(需要深拷貝進行修改)

二:proxy的優點:

1.直接監聽物件而非屬性

2.直接監聽陣列的變化

3.攔截的方式有很多種(有13種,set,get,has)

4.proxy返回一個新物件,可以操作新物件達到目的

三:proxy的缺點:

proxy有相容性問題,不能用polyfill來相容(polyfill主要撫平不同瀏覽器之間的對js實現的差異)

四:實現vue3雙向繫結

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div></div>
    <script>
        const toProxy = new WeakMap(); //存放的是代理後的物件
        const toRaw = new WeakMap();   //存放的是代理前的物件
        function trigger() {
            console.log('觸發檢視更新')
        }
        function isObject(target) {
            return typeof target === 'object' && target !== null;
        }
        function reactive(target) {
            if (!isObject(target)) {
                return target;
            }
            let proxy = toProxy.get(target)
            // 如果代理表中已經存在了  就把這個結果返回
            if (proxy) {
                return proxy
            }
            // 如果這個物件已經被代理過了  就直接返回
            if (toRaw.has(target)) {
                return target;
            }
            const handlers = {
                set(target, key, value, receiver) {
                    if (target.hasOwnProperty(key)) {
                        trigger()

                    }
                    return Reflect.set(target, key, value, receiver)
                },
                get(target, key, value, receiver) {
                    const res = Reflect.get(target, key, receiver)
                    if (isObject(target[key])) {
                        return reactive(res)
                    }
                    return res;
                },
                deleteProperty(target, key) {
                    return Reflect.deleteProperty(target, key)
                }
            }
            let observed = new Proxy(target, handlers)
            toProxy.set(target, observed);
            toRaw.set(observed, target)
            return observed
        }
        let obj = {
            name: '溫小鹿',
            arr: [1, 2, 3]
        }
        // let p = reactive(obj)
        // p.name = 'jw'
        // let arr = [1, 2 ,3];
        // let p = reactive(arr)
        // p.push(4);
        // console.log(p)

        let p = reactive(obj)
        p = reactive(p)
        p = reactive(p)
        p.arr.push(4)
        console.log(p)
    </script>
</body>

</html>