淺談Vue中的數據綁定的實現,以及Vue3.0的proxy

在開發過程當中,咱們時常會遇到這樣一種狀況:當vue的data裏邊聲明或者已經賦值過的對象或者數組(數組裏邊的值是對象)時,向對象中添加新的屬性,若是更新此屬性的值,是不會更新視圖的。javascript

根據官方文檔定義:若是在實例建立以後添加新的屬性到實例上,它不會觸發視圖更新。 受現代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測到對象屬性的添加或刪除。因爲 Vue 會在初始化實例時對屬性執行 getter/setter 轉化過程,因此屬性必須在 data 對象上存在才能讓 Vue 轉換它,這樣才能讓它是響應。vue

固然針對這種狀況,官方也提供瞭解決方案,以下: Vue 不容許在已經建立的實例上動態添加新的根級響應式屬性 (root-level reactive property)。然而它可使用Vue.set(obj, key, val)方法將響應屬性添加到嵌套的對象上: Vue.set(vm.obj, 'e', 0) 您還可使用 vm.$set 實例方法,這也是全局 Vue.set 方法的別名: this.$set(this.obj, 'e', 2)java

那麼爲何會這樣呢?仍是要從Vue實現數據綁定的原理提及(Object.defineProperty),假設咱們把Vue數據綁定精簡爲下列代碼:

<div>
    <h3>展現姓名:<span id="name"></span></h3>
    <p>輸入姓名:<input type="text" oninput="inputHandler('name', this.value)" /></p>
    <h3>展現電話號碼:<span id="phone"></span></h3>
    <p>輸入電話號碼:<input type="text" oninput="inputHandler('phone', this.value)" /></p>
</div>

<script type="text/javascript">
	// 須要監聽的對象 ----
    var obj = {
        name: null
    }

    // 定義監聽 -  Object.defineProperty的實現
    for(let key in obj) {
        let val = obj[key];
        Object.defineProperty(obj, key, {
            enumerable: true,
            configurable: true,
            get() {
                return val;
            },
            set(newValue) {
                if(val === newValue) {
                    return;
                }
                document.getElementById(key).innerText = newValue;
                val = newValue;
            }
        })
    }
    
    var inputHandler = function(key, value) {
        obj[key] = value;
    }
</script>
複製代碼

那麼重點來了,咱們有沒有辦法實現新增屬性也能自動綁定呢?答案固然是有,也就是即將推出的Vue3.0也採用的ES6的新API - Proxy,用新的Proxy 改些後的代碼以下:

<div>
    <h3>展現姓名:<span id="name"></span></h3>
    <p>輸入姓名:<input type="text" oninput="inputHandler('name', this.value)" /></p>

    <h3>展現電話號碼:<span id="phone"></span></h3>
    <p>輸入電話號碼:<input type="text" oninput="inputHandler('phone', this.value)" /></p>
</div>

<script type="text/javascript">
	// 須要監聽的對象 ----
    var obj = {
        name: null
    }

    obj = new Proxy(obj, {
        get: function(target, prop) {
            console.log('proxy get:', target, prop);
        },

        set: function(target, prop, value) {
            document.getElementById(prop).innerText = value;
            target[prop] = value;
            console.log('proxy:', target, prop, value);
        }
    })
    
    var inputHandler = function(key, value) {
        obj[key] = value;
    }
</script>
複製代碼

運行起來看看,是否是不使用$set,就能實現新增屬性的綁定呢?期待Vue3.0的到來。react

相關文章
相關標籤/搜索