談及Vue中的數據雙向綁定,咱們天然而然的想到是經過v-model指令實現的。但具體是怎麼實現的呢?下面就介紹一下。javascript
v-model語法糖是vue多個基礎語法(屬性綁定 和事件綁定)的簡寫。html
原理:給表單元素input綁定經過"v-bind:"綁定value屬性的數據msg,再給表單元素input添加監聽value值改變的事件@input,給msg從新賦值。vue
代碼:java
<!-- <input type="text" v-model="msg"> --> <input :value="msg" type="text" @input="msg=$event.target.value">
vue中數據雙向綁定經過v-model實現,雙向綁定指的是視圖和內存中的數據進行雙向綁定。(經過Object.defineProperty和給元素註冊事件)node
表單元素改變數據的原理:
算法
經過給表單元素註冊input事件,將表單元素中的value值賦給vue.msg瀏覽器
<!-- 1. 把數據渲染到表單元素中 --> <!-- 2. 當你修改數據的時候,表單元素的值發生改變,視圖須要更新 --> <!-- 3. 當你使用表單元素的時候,你在修改元素的值,對應的數據也要發生改變 --> <h5></h5> <input type="text"> <script> // const vm = new Vue({data:{msg:'hi vue'}}) vm.msg = '數據' // 使用用定義能夠監聽(觀察)的屬性的。 const vm = {} const data = { msg: 'hi vue' } // 獲取dom const h5 = document.querySelector('h5') const input = document.querySelector('input') // 1. 默認渲染 h5.innerHTML = data.msg input.value = data.msg // 2.1 監聽 data中的msg的值改變 觀察 data中的msg的值改變 最終監聽的是vm的msg屬性變化 // 2.2 若是 數據改變 修改視圖 // 三個參數 給誰定義一個屬性 屬性的名稱 對象配置項(get 獲取屬性值 set 設置屬性值) Object.defineProperty(vm, 'msg', { get() { // 當獲取msg屬性值時觸發 // console.log('get') return data['msg'] }, set(newValue) { // 當設置msg屬性值時觸發 // console.log('set') // console.log(newValue) // 數據改變 data['msg'] = newValue // 修改視圖 h5.innerHTML = newValue input.value = newValue } }) // 3. 監聽 表單元素 的值改變事件 修改數據便可(上面已經實現數據驅動視圖) input.oninput = function(){ // console.log(this.value) vm.msg = this.value } </script>
整體描述:dom
Vue內部會把data中的數據經過defineProperty方法轉化爲set和get的監控方式函數
當data中的數據發生變化時,會觸發對應的set或者get性能
修改屬性值的時候,觸發set方法
訪問屬性值的時候,觸發get方法
監控數據變化的目的仍是爲了更新頁面(僅僅更新數據變化對應的DOM節點:儘量少的更新DOM)
可是完成上述要求須要底層虛擬DOM的支持
瀏覽器更新DOM比較耗時,爲了節省時間,須要儘量少的更新DOM。虛擬DOM是對真實DOM的一種描述;其組成部分虛擬節點也描述了真實的DOM節點,本質上就是普通對象
// VNODE 虛擬節點:描述了真實的DOM節點,本質上就是普通對象 { tagName: 'div' attrs: { class: "active", id: "info"} content: "hello" }
虛擬DOM也會造成一個樹狀結構,描述了真實的DOM樹(造成虛擬DOM樹和真實DOM樹的對應關係)
若是數據發生變化,那麼就會觸發虛擬DOM數的對比(diff算法,過程發生在內存中)
對比的結果是:有變化的虛擬節點的集合
上述虛擬節點須要轉化爲真實的DOM節點(下面是虛擬下面是虛擬節點轉換爲真實節點的過程)
var div = document.createElement(vnode.tagName) div.setAttibute(key, value) div.innerHTML = vnode.content
雙向數據綁定運用虛擬DOM的進一步解釋說明:
在使用defineProperty進行到set()時,會採用虛擬DOM來跟新視圖;虛擬DOM有新、舊兩份數據存儲在內存中,每次監測到數據改變時,計算機會經過diff算法對比兩份數據的區別,獲得有變化的虛擬節點的集合,並將它們轉換爲真實的DOM節點更新到頁面中。
採用上面方式的緣由就是瀏覽器解析完整DOM樹的時間、性能消耗,要遠比內存對比數據再進行局部渲染的消耗大得多。內存處理數據的速度要比瀏覽器快的多。