學習vue框架一個簡單MVVM框架的學習筆記---記錄僅為個人學習
學習vue框架一個簡單MVVM框架的學習筆記—記錄僅為個人學習
參考資料:
理解vue原理,實現簡單vue框架
解析vue原理,如何實現雙向繫結
vue雙向繫結原理
一設計思路
因為我是在看了這幾篇文章才稍微理解了vue的雙向繫結,所以我這裡有一點上帝視角的意思。就好像應當這樣的。
如果要實現一個簡單的雙向繫結的MVVM框架至少要以下幾點:
1.首先要會利用Object.defineProperty,將data物件裡的資料繫結上getter/setter,以便攔截對資料的訪問和設定,稱之為Observer(觀察者);
2.需要解析dom,解析出相關指令和文字,並對它進行相關操作,稱之Compiler 。
3.需要一個用以監聽資料變化的監聽佇列和發生改變時釋出訊息函式的Dep簡稱為釋出者Dep。
4.有了偵聽佇列就要有一個監聽器,進行接受dom的變化,並執行相關的更新dom,稱之為Watcher
5.最後需要一個可以公共入口,協調以上步驟,稱之為vue
簡單說一下總體步驟,
<div id='app'>
<p v-text='textStr'></p>
</div>
var vm = new MVVM({
el:'#app',
data:{
textStr:'this is a text'
}
})
首先
1.MVVM介面傳入物件options,之後MVVM進行相關的資料繫結,賦值和代理。
2.執行Observer(this.$data)來進行第一大步資料繫結上getter/setter
3.繫結後執行compiler進行dom的解析,最後執行new Watch()建立一個新的監聽器。
4.執行Watcher過程中會將此偵聽器加入偵聽佇列Dep中,建立Watcher過程中會執行一次update更新函式,更新dom中的資料。
5.之後每次改變資料會呼叫setter來執行Dep的notify來更新資料。
二、實現Observer
這裡就簡單的說一下過程方便我本人再回憶
1.遍歷object中的每一個key值,Object.defineProperty繫結getter/setter,之後要記得遍歷子節點即observe(val)。
2.監視物件時記得var dep = new Dep()並在getter中Dep.target && dep.addSub(Dep.target);將watcher偵聽器加入dep中, 之後在setter中記得執行dep.notify()來執行dom中的資料資料更新
三,實現compiler
簡單陳述一下:用遍歷得到文件碎片返回fragment,之後this.compile(this. el.appendChild(this.$fragment)。其中compile函式是主要解析dom的,當然要記得迴圈遍歷每一個子節點。當然以nodeType進入不同的函式,之後執行不同的處理例如:modelHandler,textHandler,htmlHandler。裡面再繫結監聽者bindWatcher()裡面有更新資料函式。
四,實現watcher
主要功能就是監聽資料變化並執行update資料更新。
Watcher作用域中get函式獲取value值並把此監聽器加入監聽佇列。
update函式作用就是獲取新的newVal,執行compiler傳入的回撥函式進行資料更新。
五,實現Dep釋出者
主要功能是將偵聽器掛載到上面並在要執行釋出訊息notify時呼叫watcher的更新函式。
六,實現Vue的介面和建立
第一點
options = Object.assign({},
{
computed: {},
methods : {}
},
options);
data和computed代理到vue物件上,而methods方法直接掛載到vue上不用代理。
var ob = new Observer(this.
data繫結setter/getter。
new Compiler({el: this.$el, vm: this});解析dom結構並在其中掛載相應的偵聽器。
七,父子元件部分
即component模組,過了好久才補充的,我就簡單講一下父向子傳模組吧。
基本思想就是解析dom元素時檢查標籤是否與components的標籤一樣,若一樣就按照子元件的template建立dom節點之後,相當於再new 一個MVVM,之後再把這個dom節點插入原來父節點的地方,當然裡面有許多複雜的操作,這裡詳細講。
八,遇到的一些需要注意的問題
觀察者中Observer
1,observeObject方法要繫結時,記得如果是物件要遍歷子節點即this.observe(val)。
2,還有監控陣列,但這一點有點難。
Compiler
1,編譯元素節點時,要記得在結尾遍歷子元素節點。
過程基本為1->執行nodeToFragment獲取元素文件碎片
2->執行compile()編譯dom,compile根據節點是元素還是文件來進行分類。之後根據v-XXX指令來解析跳到XXXHandler處理函式,其中再執行bindWatcher()來新建繫結偵聽器。最後有一個updater物件,裡面有各種實現更新函式,建立Watcher將更新函式傳入。
3-> this.
fragment)將文件碎片插入dom中
Watcher
1.其中Watcher作用域中有兩個函式get()是用來將偵聽器加入偵聽佇列,並獲取相應的資料val。
update()用來執行get(),並更新dom執行compiler傳進來的更新資料函式。
Dep
1.兩個函式addSub()增加監聽器, notify()執行所有監聽器的更新函式。