记一次对vue双向绑定的理解
之前有看過一次vue雙向綁定原理實現相關的博客,看得似懂非懂的,然后也就擱淺了。
昨天腦海里又突然燃起了要不這塊搞懂的沖動,于是乎又開始了一輪博客轟炸,綜合研究了多位大神寫得關于vue雙向綁定的實現原理,然后結合自己的一些理解,就有了這篇文章了。
關于雙向綁定,我所知的兩類:(小的不才,目前只接觸過vue和angular)
一是angular1的臟檢查機制
二是vue的數據劫持配合觀察者模式(網上有很多寫的都是訂閱-發布模式,我特意去查看了這兩種模式有什么區別,大致是說觀察者模式中觀察者是被動接收統一的消息,而訂閱-發布模式中是訂閱者是可以自定義接收行為的,而vue中watcher對象中update方法都是一致的,就是同步數據,所有鄙人覺得用觀察者模式來形容可能會更貼切些,如果理解的不對,歡迎大家輕吐~)
下面我先貼一張我整理的原理圖
我的理解:
1.編譯器會解析DOM元素,比如碰到v-model指令時,會對該DOM元素添加input監聽事件,當事件發生時,給data屬性值賦值,進而觸發該屬性的setter方法(這樣就實現了從view到model的同步);除了增加監聽事件外,還會實例化一個watch對象。
2.實例化一個watch對象主要有兩個作用,一個是通過調用data元素的getter方法,觸發Dep的add方法將watcher對象加入到訂閱器中(為了防止在除watch對象中其他其他調用了getter方法,進而重復添加監聽器,我們在watcher對象中給Dep添加一個不為空全局變量,當全局變量不為空時才添加,添加完后又將全局變量置為null),第二個作用是聲明一個update方法,用來接收到訂閱器的通知后同步數據給節點進行渲染。
3.上面我們已經在屬性的getter方法中將watcher對象加入了訂閱器,當model層屬性值發生變化時會觸發setter方法,我們在setter中再去觸發訂閱器的notify,并在notify中觸發watcher對象的update方法(這樣就實現了從model到view的同步)
從圖中也可看出,主要有4大塊,我們依照流程圖的順序來分析一下:
- compile
先擼一波
代碼分析:
(1)使用 DocumentFragment 處理節點,速度和性能遠遠優于直接操作 DOM。Vue 進行編譯時,就是將掛載目標的所有子節點劫持(真的是劫持,通過 append 方法,DOM 中的節點會被自動刪除)到 DocumentFragment 中,經過一番處理后,再將 DocumentFragment 整體返回插入掛載目標。
(2)node.nodeType判斷節點類型,如果是元素的話,判斷該元素有沒有v-model
屬性,有則監聽input事件,將輸入框的值同步到變量中,同時實例化一個watcher。如果是文本的話,看是不是符合{{}}正則表達式,符合則是我們需要加入訂閱器的對象。
- watcher-觀察者
代碼分析:
(1)實例化watcher對象是有獲取對象的值this.vm[this.name],這對出發該對象的get方法,而在對象的get方法中就可以把這個觀察者加入到Dep中了,后面oberver可以看到
(2)update()方法就是觀察者接收到通知后用來同步數據給節點進行渲染的作用。
- Observe-數據監測器
代碼分析:
(1)數據監測器用到的知識點就是ES5的Object.defineProperty方法,改寫對象的set和get方法,在set方法中通知觀察該對象的所有watcher更新,在get方法中實現的是當watcher第一次調用get方法的時候把自己綁定給訂閱器進行管理
- Dep-訂閱器
(1)它的addsub方法在observer的get方法中被調用,notify方法在observer的set方法中被調用
至此,四大塊就分析完了,回過頭來再去看那張圖,你理解的會更深刻一點。
下面終極大boss出場了MVVM.js
index.html
<!DOCTYPE html><head></head><body><div id="app"><input type="text" id="a" v-model="text">{{text}}</div><script src="src/Dep.js"></script><script src="src/Observe.js"></script><script src="src/Watcher.js"></script><script src="src/Compile.js"></script><script src="src/MVVM.js"></script><script>var vm = new Vue({el: 'app',data: {text: 'hello world'}});</script></body> </html>代碼分析:
這里自定義了vue對象,解析包含的html片段,實現的雙向綁定。
··························分隔符···························
參考資料:
http://www.cnblogs.com/kidney/p/6052935.html?utm_source=gold_browser_extension
總結
以上是生活随笔為你收集整理的记一次对vue双向绑定的理解的全部內容,希望文章能夠幫你解決所遇到的問題。