Vue 響應式原理簡易 MVVM 三步走第一步 (數據劫持)

前言

Vue響應式原理主要經過如下三點來實現
  1. 經過數據劫持監聽數據變化
  2. 經過模板編譯進行數據渲染
  3. 經過發佈訂閱模式實現視圖與數據的同步

image

下面咱們將經過這三點來實現一個簡易的mvvm, 從而加深對Vue響應式的理解bash

數據劫持

Vue2實現數據劫持是利用ES5的 Object.defineProperty , 利用它會爲對象添加get/set方法,從而監聽屬性的讀取與修改。app

// html代碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h1>{{name}}</h1>
        <p>身份:{{about.title}}</p>
        <p>夢想:找到{{about.dream}},併成爲海賊王。</p>
        <p>惡魔果實:{{about.fruit}}。</p>
        他的標誌性特徵是一頂草帽,所以常被直接稱呼爲「{{about.alias}}」
    </div>
    <!--實現的mvvm-->
    <script src="./mvvm.js"></script>
    <script>
        let mvvm = new Mvvm({
            el: '#app',
            data: { 
                name: '蒙奇·D·路飛',
                about: {
                    title: '草帽海賊團船長',
                    dream: 'ONE PIECE',
                    fruit: '超人系橡膠果實',
                    alias: '草帽'
                }
            }
        });
    </script>
</body>
</html>
複製代碼

簡易Mvvm第一步

// 建立一個Mvvm構造函數,參數是一個選項對象
class Mvvm {
    constructor(options = {}) {
        this.$options = options;
        this._data = this.$options.data;
        
        // 經過 observe 劫持data對象,從而監聽其內部屬性
        observe(this._data)
    }
}
複製代碼

實現 Observe

function Observe(data) {
    for (let key in data) {
        let val = data[key]
        // 開頭調用 observe 判斷當前屬性是否爲一個對象,
        // 若是是一個對象, 則遞歸調用Observe 確保監聽到深層屬性
        observe(val)
        
        // 經過 Object.defineProperty 爲每個屬性添加get/set方法
        // 當屬性被讀取時會觸發get ,屬性被修改時觸發set
        Object.defineProperty(data, key, {
            configurable: true,
            get() {
                return val;
            },
            set(newVal) {
                if (val === newVal) return;
                val = newVal;
                
                // 這裏咱們打一個log 測試時使用
                console.log('數據被修改')
                
                // 確保新屬性的值是一個對象時也能監聽到其內部屬性
                observe(newVal);
            }
        })
    }
}

function observe(data) {
    if(!data || typeof data !== 'object') return;
    return new Observe(data)
}
複製代碼

測試一下

數據劫持基本已經完成,下面咱們來看一看observe是否有效mvvm

打開控制檯,輸入mvvm, 能夠看到_data中的屬性都被添加上了get/set方法函數

咱們測試一下修改屬性是否能觸發set, 能夠看到數據修改並打印了logpost

爲何要再set中調用 observe(newVal)?

當咱們將一個屬性值修改成一個對象,這個新對象中的屬性是沒有被observe監聽到的,因此咱們須要再set時調用一下observe來確能監聽到新對象的屬性測試

例如: 當咱們將name屬性值修改成一個對象,當沒有在set中調用observe時是這樣的ui

調用了observe(newVal)時

好了,如今咱們完成了第一步 數據劫持,下一篇咱們來完成第二部 模板解析Compile

參考資料

相關文章
相關標籤/搜索