1. 程式人生 > >轉 vue實現雙向資料繫結之原理及實現篇 vue的雙向繫結原理及實現

轉 vue實現雙向資料繫結之原理及實現篇 vue的雙向繫結原理及實現

轉自:canfoo#!

vue的雙向繫結原理及實現

前言

先上個成果圖來吸引各位:

程式碼:                                                                                 效果圖:

 

是不是看起來跟vue的使用方式差不多?接下來就來從原理到實現,從簡到難一步一步來實現這個SelfVue。

本文主要介紹兩大內容:

1. vue資料雙向繫結的原理。

2. 實現簡單版vue的過程,主要實現{{}}、v-model和事件指令的功能。

相關程式碼地址:https://github.com/canfoo/self-vue

vue資料雙向繫結原理

vue資料雙向繫結是通過資料劫持結合釋出者-訂閱者模式的方式來實現的,我們可以先來看一下通過控制檯輸出一個定義在vue初始化資料上的物件是個什麼東西。

程式碼:

複製程式碼
var vm = new Vue({
    data: {
        obj: {
            a: 1
        }
    },
    created: function () {
        console.log(this.obj);
    }
});
複製程式碼

結果:

我們可以看到屬性a有兩個相對應的get和set方法,為什麼會多出這兩個方法呢?因為vue是通過Object.defineProperty()來實現資料劫持的。

Object.defineProperty( )是用來做什麼的?它可以來控制一個物件屬性的一些特有操作,比如讀寫權、是否可以列舉,這裡我們主要先來研究下它對應的兩個描述屬性get和set,如果還不熟悉其用法,

請點選這裡閱讀更多用法。

在平常,我們很容易就可以打印出一個物件的屬性資料:

var Book = {
  name: 'vue權威指南'
};
console.log(Book.name);  // vue權威指南

如果想要在執行console.log(book.name)的同時,直接給書名加個書名號,那要怎麼處理呢?或者說要通過什麼監聽物件 Book 的屬性值。這時候Object.defineProperty( )就派上用場了,程式碼如下:

複製程式碼
var Book = {}
var name = '';
Object.defineProperty(Book, 'name', {
  set: function (value) {
    name = value;
    console.log('你取了一個書名叫做' + value);
  },
  get: function () {
    return '《' + name + '》'
  }
})
 
Book.name = 'vue權威指南';  // 你取了一個書名叫做vue權威指南
console.log(Book.name);  // 《vue權威指南》
複製程式碼

我們通過Object.defineProperty( )設定了物件Book的name屬性,對其get和set進行重寫操作,顧名思義,get就是在讀取name屬性這個值觸發的函式,set就是在設定name屬性這個值觸發的函式,所以當執行 Book.name = 'vue權威指南' 這個語句時,控制檯會打印出 "你取了一個書名叫做vue權威指南",緊接著,當讀取這個屬性時,就會輸出 "《vue權威指南》",因為我們在get函式裡面對該值做了加工了。如果這個時候我們執行下下面的語句,控制檯會輸出什麼?

console.log(Book);

結果:

乍一看,是不是跟我們在上面列印vue資料長得有點類似,說明vue確實是通過這種方法來進行資料劫持的。接下來我們通過其原理來實現一個簡單版的mvvm雙向繫結程式碼。

思路分析

實現mvvm主要包含兩個方面,資料變化更新檢視,檢視變化更新資料

關鍵點在於data如何更新view,因為view更新data其實可以通過事件監聽即可,比如input標籤監聽 'input' 事件就可以實現了。所以我們著重來分析下,當資料改變,如何更新檢視的。

資料更新檢視的重點是如何知道資料變了,只要知道資料變了,那麼接下去的事都好處理。如何知道資料變了,其實上文我們已經給出答案了,就是通過Object.defineProperty( )對屬性設定一個set函式,當資料改變了就會來觸發這個函式,所以我們只要將一些需要更新的方法放在這裡面就可以實現data更新view了

思路有了,接下去就是實現過程了。

前言

先上個成果圖來吸引各位:

程式碼:                                                                                 效果圖:

 

是不是看起來跟vue的使用方式差不多?接下來就來從原理到實現,從簡到難一步一步來實現這個SelfVue。

本文主要介紹兩大內容:

1. vue資料雙向繫結的原理。

2. 實現簡單版vue的過程,主要實現{{}}、v-model和事件指令的功能。

相關程式碼地址:https://github.com/canfoo/self-vue

vue資料雙向繫結原理

vue資料雙向繫結是通過資料劫持結合釋出者-訂閱者模式的方式來實現的,我們可以先來看一下通過控制檯輸出一個定義在vue初始化資料上的物件是個什麼東西。

程式碼:

複製程式碼
var vm = new Vue({
    data: {
        obj: {
            a: 1
        }
    },
    created: function () {
        console.log(this.obj);
    }
});
複製程式碼

結果:

我們可以看到屬性a有兩個相對應的get和set方法,為什麼會多出這兩個方法呢?因為vue是通過Object.defineProperty()來實現資料劫持的。

Object.defineProperty( )是用來做什麼的?它可以來控制一個物件屬性的一些特有操作,比如讀寫權、是否可以列舉,這裡我們主要先來研究下它對應的兩個描述屬性get和set,如果還不熟悉其用法,請點選這裡閱讀更多用法。

在平常,我們很容易就可以打印出一個物件的屬性資料:

var Book = {
  name: 'vue權威指南'
};
console.log(Book.name);  // vue權威指南

如果想要在執行console.log(book.name)的同時,直接給書名加個書名號,那要怎麼處理呢?或者說要通過什麼監聽物件 Book 的屬性值。這時候Object.defineProperty( )就派上用場了,程式碼如下:

複製程式碼
var Book = {}
var name = '';
Object.defineProperty(Book, 'name', {
  set: function (value) {
    name = value;
    console.log('你取了一個書名叫做' + value);
  },
  get: function () {
    return '《' + name + '》'
  }
})
 
Book.name = 'vue權威指南';  // 你取了一個書名叫做vue權威指南
console.log(Book.name);  // 《vue權威指南》
複製程式碼

我們通過Object.defineProperty( )設定了物件Book的name屬性,對其get和set進行重寫操作,顧名思義,get就是在讀取name屬性這個值觸發的函式,set就是在設定name屬性這個值觸發的函式,所以當執行 Book.name = 'vue權威指南' 這個語句時,控制檯會打印出 "你取了一個書名叫做vue權威指南",緊接著,當讀取這個屬性時,就會輸出 "《vue權威指南》",因為我們在get函式裡面對該值做了加工了。如果這個時候我們執行下下面的語句,控制檯會輸出什麼?

console.log(Book);

結果:

乍一看,是不是跟我們在上面列印vue資料長得有點類似,說明vue確實是通過這種方法來進行資料劫持的。接下來我們通過其原理來實現一個簡單版的mvvm雙向繫結程式碼。

思路分析

實現mvvm主要包含兩個方面,資料變化更新檢視,檢視變化更新資料

關鍵點在於data如何更新view,因為view更新data其實可以通過事件監聽即可,比如input標籤監聽 'input' 事件就可以實現了。所以我們著重來分析下,當資料改變,如何更新檢視的。

資料更新檢視的重點是如何知道資料變了,只要知道資料變了,那麼接下去的事都好處理。如何知道資料變了,其實上文我們已經給出答案了,就是通過Object.defineProperty( )對屬性設定一個set函式,當資料改變了就會來觸發這個函式,所以我們只要將一些需要更新的方法放在這裡面就可以實現data更新view了

思路有了,接下去就是實現過程了。