Vue2.X和Vue3.0數據響應原理實例(上)

Vue2.X數據響應原理

Object.defineProperty

Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象。javascript

Vue2.x使用屬性裏的get和set實現了數據響應。html

經常使用屬性:vue

value:該屬性對應的值。能夠是任何有效的 JavaScript 值(數值,對象,函數等)。默認爲 undefinedjava

get:一個給屬性提供 getter 的方法,若是沒有 getter 則爲 undefined。當訪問該屬性時,該方法會被執行,方法執行時沒有參數傳入,可是會傳入this對象(因爲繼承關係,這裏的this並不必定是定義該屬性的對象)。 默認爲 undefined數組

set:一個給屬性提供 setter 的方法,若是沒有 setter 則爲 undefined。當屬性值修改時,觸發執行該方法。該方法將接受惟一參數,即該屬性新的參數值。 默認爲 undefinedapp

writeable:當且僅當該屬性的writabletrue時,value才能被賦值運算符改變。默認爲 falsedom

enumrable:當且僅當該屬性的enumerabletrue時,該屬性纔可以出如今對象的枚舉屬性中。默認爲 false函數

configurable: 當且僅當該屬性的 configurable 爲 true 時,該屬性描述符纔可以被改變,同時該屬性也能從對應的對象上被刪除。默認爲 falseui

Vue從改變一個數據到發生改變的過程

Vue2.X數據響應原理

實例:在頁面上初始化「I am Hector」,延時2s,修改「Hector」部分的值,修改成「Hector Real」,頁面顯示「I am Hector Real」,實現數據響應。this

建立頁面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>LearnVue3.0</title>
</head>
<body>
    <div id="app"></div>
    <script type="text/javascript" src="test.js"></script>
    <script type="text/javascript"> const vm = new vue(); // 延時2s修改數據 setTimeout(function () { console.log('change'); console.log(vm.$data); vm.$data.a = 'Hector Real'; }, 2000); </script>
</body>
</html>
複製代碼

test.js中使用Object.defineProperty實現數據響應:

function vue() {
    // 固定對象和dom
    this.$data = {
        a: 'Hector'
    };
    this.el = document.getElementById('app');
    // 須要渲染的文字
    this._html = "";
    // 初始化
    this.observe(this.$data);
    this.render();
}

// 數據監聽
vue.prototype.observe = function (obj) {
    let self = this;
    let value;
    // 解決只能對某個屬性進行defineProperty的問題
    // 因此針對傳入obj進行了for-in遍歷
    for (let key in obj) {
        value = obj[key];
        if (typeof value === 'object') {
            // 再對這個對象設置監聽
            this.observe(value);
        } else {
            Object.defineProperty(this.$data, key, {
                // 依賴收集
                get: function () {
                    return value;
                },
                // 觸發更新
                set: function (newvalue) {
                    value = newvalue;
                    self.render();
                }
            })
        }
    }
}

// 渲染
vue.prototype.render = function () {
    this._html = "I am " + this.$data.a;
    this.el.innerHTML = this._html;
}
複製代碼

在Chrome中運行,結果頁面顯示: I am Hector Real

在Chrome的console中的log:

數組特性化

針對數組特性化處理:

let arraypro = Array.prototype;
// 爲何要create再次建立對象,create是深拷貝,不影響以前的arraypro
let arrayob = Object.create(arraypro);
// 定義哪些方法觸發更新
let arr = ["push", "pop", "shift"];

// arr裏的方法,既能保持原有方法,又能觸發更新
// 裝飾者模式
arr.forEach(function (method, index) {
    // 對本身的push方法重寫
    arrayob[method] = function () {
        let ret = arraypro[method].apply(this, arguments);
        // self.render();
        console.log('檢測到數組變化,觸發更新');
        return ret;
    }
});
複製代碼

在Chrome中console運行示例:

let arr = [];
arr.__proto__ = arrayob;
arr.push(1);
複製代碼

結果顯示:


歡迎關注個人公衆號,謝謝你們!

相關文章
相關標籤/搜索