中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

vue3結構賦值失去響應式引發的問題怎么解決

發布時間:2022-06-30 09:44:37 來源:億速云 閱讀:1312 作者:iii 欄目:開發技術

這篇文章主要介紹“vue3結構賦值失去響應式引發的問題怎么解決”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“vue3結構賦值失去響應式引發的問題怎么解決”文章能幫助大家解決問題。

    原始值的響應式系統的實現

    在理解原始值的響應式系統的實現,我們先來溫習一下proxy 的能力!

    const obj = {
      name: 'win'
    }
    const handler = {
      get: function(target, key){
        console.log('get--', key)
        return Reflect.get(...arguments)  
      },
      set: function(target, key, value){
        console.log('set--', key, '=', value)
        return Reflect.set(...arguments)
      }
    }
    const data = new Proxy(obj, handler)
    data.name = 'ten'
    console.log(data.name,'data.name22')

    上述代碼中,我們發現,proxy 的使用本身就是對于 對象的攔截, 通過new Proxy 的返回值,攔截了obj 對象如此一來,當你 訪問對象中的值的時候,他會觸發 get 方法, 當你修改對象中的值的時候 他會觸發 set方法但是到了原始值的時候,他沒有對象啊,咋辦呢,new proxy 排不上用場了。無奈之下,我們只能包裝一下了,所以就有了使用.value訪問了

    我們來看看具體實現:

    import { reactive } from "./reactive";
    import { trackEffects, triggerEffects } from './effect'
    export const isObject = (value) => {
        return typeof value === 'object' && value !== null
    }
    // 將對象轉化為響應式的
    function toReactive(value) {
        return isObject(value) ? reactive(value) : value
    }
    class RefImpl {
        public _value;
        public dep = new Set; // 依賴收集
        public __v_isRef = true; // 是ref的標識
        // rawValue 傳遞進來的值
        constructor(public rawValue, public _shallow) {
            // 1、判斷如果是對象 使用reactive將對象轉為響應式的
            // 淺ref不需要再次代理
            this._value = _shallow ? rawValue : toReactive(rawValue);
        }
        get value() {
            // 取值的時候依賴收集
            trackEffects(this.dep)
            return this._value;
        }
        set value(newVal) {
            if (newVal !== this.rawValue) {
                // 2、set的值不等于初始值 判斷新值是否是對象 進行賦值
                this._value = this._shallow ? newVal : toReactive(newVal);
                // 賦值完 將初始值變為本次的
                this.rawValue = newVal
                triggerEffects(this.dep)
            }
        }
    }

    上述代碼,就是對于原始值,的包裝,他被包裝為一個對象,通過get value 和set value 方法來進行原始值的訪問,從而導致必須有.value 的操作 ,這其實也是個無奈的選擇

    相當于兩瓶毒藥,你得選一瓶 魚與熊掌不可兼得

    為什么ES6 解構,不能隨意使用會破壞他的響應式特性

    第一個問題終于整明白了,那么我們來看看最重要的第二個問題,為什么結構賦值,會破壞響應式特性

    proxy背景

    在開始之前,我們先來討論一下為什么要更改響應式方案

    vue2 基于Object.defineProperty  ,但是他有很多缺陷,比如 無法監聽數組基于下標的修改,不支持 Map、Set、WeakMap 和 WeakSet等缺陷 

    其實這些也也不耽誤我們開發, vue2到現在還是主流,

    我的理解就是與時俱進, 新一代的版本,一定要緊跟語言的特性,一定要符合新時代的書寫風格,雖然proxy相對于Object.defineProperty 有很多進步, 但是也不是一點缺點都沒有,你比如說 不兼容IE

    天底下的事情,哪有完美的呢?尤大的魄力就在于,舍棄一點現在,博一個未來!

    實現原理

    在理解了背景之后,我們再來假模假式的溫習一下proxy 原理,雖然這個都被講爛了。

    但是,寫水文,講究什么:倆字-連貫

            const obj = {
                count: 1
            };
            const proxy = new Proxy(obj, {
                get(target, key, receiver) {
                    console.log("這里是get");
                    return Reflect.get(target, key, receiver);
                },
                set(target, key, value, receiver) {
                    console.log("這里是set");
                    return Reflect.set(target, key, value, receiver);
                }
            });
            
            console.log(proxy)
            console.log(proxy.count)

    以上代碼就是Proxy的具體使用方式,通過和Reflect 的配合, 就能實現對于對象的攔截

    vue3結構賦值失去響應式引發的問題怎么解決

    如此依賴,就能實現響應式了,大家可以發現,這個obj的整個對象就被攔截了,但是你發現對象在嵌套深一層

    比如:

        const obj = {
                count: 1,
                b: {
                    c: 2
                }
            };
         console.log(proxy.b)
         console.log(proxy.b.c)

    他就無法攔截了,我們必須要來個包裝

        const obj = {
                a: {
                    count: 1
                }
            };
            function reactive(obj) {
                return new Proxy(obj, {
                    get(target, key, receiver) {
                        console.log("這里是get");
                        // 判斷如果是個對象在包裝一次,實現深層嵌套的響應式
                        if (typeof target[key] === "object") {
                            return reactive(target[key]);
                        };
                        return Reflect.get(target, key, receiver);
                    },
                    set(target, key, value, receiver) {
                        console.log("這里是set");
                        return Reflect.set(target, key, value, receiver);
                    }
                });
            };
            const proxy = reactive(obj);

    好了,原理搞完了,我們來正式研究一下現在列舉一下我知道的響應式失去的幾個情況:

    • 1、解構 props 對象,因為它會失去響應式

    • 2、 直接賦值reactive響應式對象

    • 3、 vuex中組合API賦值

    解構 props 對象,因為它會失去響應式

           const obj = {
                a: {
                    count: 1
                },
                b: 1
            };
                //reactive 是上文中的reactive
               const proxy = reactive(obj);
            const {
                a,
                b
            } = proxy;
            console.log(a)
            console.log(b)
            console.log(a.count)

    vue3結構賦值失去響應式引發的問題怎么解決

    上述代碼中,我們發現, 解構賦值,b 不會觸發響應式a如果你訪問的時候,會觸發響應式

    這是為什么呢?別急我們一個個解釋?先來討論為什么解構賦值,會丟失響應式呢?我們知道解構賦值,區分原始類型的賦值,和引用類型的賦值,

    原始類型的賦值相當于按值傳遞, 引用類型的值就相當于按引用傳遞

    就相當于:

       // 假設a是個響應式對象
      const a={ b:1}
      // c 此時就是一個值跟當前的a 已經不沾邊了
      const c=a.b
    // 你直接訪問c就相當于直接訪問這個值 也就繞過了 a 對象的get ,也就像原文中說的失去響應式

    那為啥a 具備響應式呢?

    因為a 是引用類型,我們還記得上述代碼中的一個判斷嗎。如果他是個object 那么就重新包裝為響應式

    正式由于當前特性,導致,如果是引用類型, 你再去訪問其中的內容的時候并不會失去響應式

      // 假設a是個響應式對象
     const a={ b:{c:3}}
     // 當你訪問a.b的時候就已經重新初始化響應式了,此時的c就已經是個代理的對象
     const c=a.b
    // 你直接訪問c就相當于訪問一個響應式對象,所以并不會失去響應式

    以上就大致解釋了為什么解構賦值,可能會失去響應式,我猜的文檔中懶得解釋其中緣由,索性就定了個規矩,您啊!

    就別用了,省的以為是vue的bug,提前改變用戶的使用習慣!不慣著

    直接賦值reactive響應式對象

    我們最初使用vue3的時候,指定會寫出以下代碼

     const vue = reactive({ a: 1 })
     vue = { b: 2 }

    然后就發出疑問reactive不是響應式的嗎? 為啥我賦值了以后,他的響應式就沒了 ,接著破口大罵,垃圾vue

    其實啊,這就是您對于js 原生的概念不清除,其實尤大 已經做了最大的努力,來防止你進行錯誤操作了

    比如,由于解構賦值的問題, 他直接禁止了reactive的解構賦值

    vue3結構賦值失去響應式引發的問題怎么解決

    當你用解構賦值操作的時候,他直接禁用了那有人又問了, 為啥props 不給禁用了呢?因為你的props 的數據可能不是響應式的啊,不是響應式的,我得能啊,尤大他也不能干涉用戶使用新語法啊

    所以還是那句話:框架現在的呈現,其實充滿了取舍,有時候真是兩瓶毒藥,挑一瓶!

    回歸正題,我們再來說說 原生js 語法,首先需要確認的是,原生js 的引用類型的賦值,其實是 按照引用地址賦值!

     // 當reactive 之后返回一個代理對象的地址被vue 存起來,
     // 用一個不恰當的比喻來說,就是這個地址具備響應式的能力
     const vue = reactive({ a: 1 })
     //  而當你對于vue重新賦值的時候不是將新的對象賦值給那個地址,而是將vue 換了個新地址
     // 而此時新地址不具備響應式,可不就失去響應式了嗎
     vue = { b: 2 }

    以上就是reactive失去響應式的解釋,所以這個也是很多用戶罵罵咧咧的原因。不符合他的使用習慣了,這都是被vue2 培養起來的一代

    在這里我要替,尤大說句公道話,人家又沒收你錢,還因為他,你有口飯吃,您自己不能與時俱進,擁抱新事物,那是您沒能耐,這是典型的端起碗吃肉,放下筷子罵娘

    vuex中組合API賦值

    在vuex 用賦值也可能會失去響應式:

    import { computed } from 'vue'
    import { useStore } from 'vuex'
    export default {
      setup () {
        const store = useStore()
        return {
          // 在 computed 函數中訪問 state
          count: computed(() => store.state.count),
    
          // 在 computed 函數中訪問 getter
          double: computed(() => store.getters.double)
        }
      }
    }

    以上代碼中我們發現store.getters.double 必須用computed 包裹起來,其實道理是一樣的,也是變量賦值的原因,在這里我們就不再贅述!

    關于“vue3結構賦值失去響應式引發的問題怎么解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    青州市| 丰宁| 白山市| 东丽区| 九寨沟县| 错那县| 郴州市| 苍山县| 灵石县| 黔南| 永嘉县| 西贡区| 福鼎市| 金沙县| 石台县| 淮滨县| 大关县| 中卫市| 青河县| 凌海市| 柏乡县| 浮梁县| 永丰县| 德安县| 沭阳县| 冀州市| 大城县| 彭州市| 海宁市| 吐鲁番市| 日喀则市| 万盛区| 上饶县| 思茅市| 靖宇县| 清镇市| 定州市| 神农架林区| 固阳县| 文山县| 玛沁县|