vue源碼解析之數據代理

Vue你們都不陌生了,用的人也不少,但你們對裏面的數據代理,模板解析渲染,v-開頭的事件指令和通常指令,數據強制綁定,雙向數據綁定如何實現的是否也產生過好奇,接下來幾篇,咱們來一塊兒探討一下這些東西,首先從比較簡單的數據代理開始。 數據代理就是經過一個對象代理來對另外一個對象中的屬性實現讀和寫的操做。好處就是很大程度上方便了咱們操做數據。 在vue中,咱們是否是常常經過this.msg就拿到了data中的msg屬性值。 其實this就是指向new Vue構造函數建立出來的vm實例,經過數據代理來實現對data對象中全部屬性的讀寫操做,咱們先寫個vue的實例對象,就像下面這樣:html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="./vue.js"></script>
</head>
<body>
    <div id="test">
        {{msg}}
    </div>

    <script>
        const vm = new Vue({
            el: '#test',
            data:{
                msg: '天氣不錯'
            }
        })
        console.log(vm)
    </script>
</body>
</html>
複製代碼

當咱們用vm.msg也能夠拿到data對象中的msg屬性。 打印出來的vm是這樣的: vue

在這裏插入圖片描述
vm拿到了data對象中的屬性和值,而且

vm._data.msg = '今天是陰天啊'
複製代碼

經過vm咱們也能完成對data對象裏面數據的更改。 那麼問題來了,vm實例是如何完成對data對象裏的屬性實現讀寫的? 在這裏,咱們就要先了解一下ES5中的Object.defineProperty()方法,看下MDN的解釋: bash

在這裏插入圖片描述
咱們須要給這個方法傳遞三個參數,第一個是要在哪一個對象上面定義屬性,第二個是要定義或修改的屬性的名稱,第三個能夠理解爲是一個配置對象,在裏面能夠配置下列屬性:
在這裏插入圖片描述
其中跟咱們講的數據代理牽扯最大的就是get和set方法。 瞭解了Object.defieProperty()方法後,咱們本身來實現一個簡單的數據代理,直接貼代碼:

let a = {
    data: {
        b: 123
    }
};
//目的:咱們想經過a.b直接拿到b裏面的數據。

//參數target:代理者,參數sourceKey:被代理者
function proxy(target,sourceKey){
    let data = target[sourceKey];
    //拿到被代理者的全部屬性名
    let keys = Object.keys(data);
    //遍歷全部屬性名,把全部屬性名經過defindeProperty方法添加到代理者身上,並定義get和set方法,實現對數據的操做
    for (let i = 0, l = keys.length; i < l; i++) {
        let key = keys[i];
        Object.defineProperty(target, key, {
            enumerable: true,
            configurable: true,
            get() {
                return this[sourceKey][key];
            },
            set(val) {
                this[sourceKey][key] = val;
            }
        });
    }
}

proxy(a, "data");

console.log(a.b); // 123
複製代碼

經過proxy函數,咱們順利的完成了a對b的數據代理,是否是很簡單?函數

相關文章
相關標籤/搜索