在實現(xiàn)雙向數(shù)據(jù)綁定的之前罗捎,先來實現(xiàn)單向數(shù)據(jù)綁定柿隙,首先大审,我們的HTML結構如下圖所示芥牌。
<div id="app">
????<input type="text" v-model="msg">
????<p>{{msg}}</p>
????<ul>
????????<li>1</li>
????????<li>{{msg}}</li>
????????<li>{{test}}</li>
????</ul>
</div>
接下來就是在JS里面實現(xiàn)單向數(shù)據(jù)綁定了,不管怎么樣峦椰,我們就像Vue一樣龄寞,直接來創(chuàng)建個Vue實例化對象。
new Vue({
????el:"app",
????data:{
????????msg:"hello world",
????????test:"單向綁定"
????}
});
而此時根本就沒有Vue這個類汤功,所以下一步直接來創(chuàng)建這個類物邑,在這個類當中,我們將傳遞過來的el屬性值賦值給id(該例中以id為例)滔金,并且也用一個data來保存?zhèn)鬟f過來的data信息色解。
function Vue(options){
????this.id=options.el;
? ??this.data=options.data;
}
好了,那么下一步的問題就是如何實現(xiàn)單向數(shù)據(jù)綁定的問題了餐茵,在Vue當中科阎,我們可以通過v-model這樣的屬性名或者{{}}的形式來進行綁值操作,很顯然钟病,我們是需要依次獲取到整個id為app標簽下的所有node節(jié)點萧恕,當其是元素節(jié)點的時候刚梭,就要查看其屬性名是否含有v-model肠阱,如果有,根據(jù)其設置的value值對應的去Vue實例化對象的data屬性中查找并賦值朴读;當其是文本節(jié)點的時候屹徘,就需要匹配{{}}里面的內(nèi)容,然后同上操作衅金。
為了講解方便噪伊,就先來實現(xiàn)根據(jù)節(jié)點所屬類別來進行賦值操作的方法,該方法需要兩個參數(shù)氮唯,一個參數(shù)為當前的節(jié)點鉴吹,一個為實例化的Vue對象。
function compile(node,vm){
? ??//當node節(jié)點為元素節(jié)點時
? ??if(node.nodeType === 1){
? ??????var attr=node.attributes;
? ??????//遍歷當前節(jié)點的所有屬性
? ??????for(let [i,v] of [].entries.call(attr)){
? ??????????if(v.nodeName=="v-model"){
? ??????????????var name=v.nodeValue;
? ??????????????node.value=vm.data[name];
? ??????????????node.removeAttribute(v.nodeName);
? ? ? ? ? ? ? }????
? ?????}
????}
? ??//當node節(jié)點為文本節(jié)點時
? ??if(node.nodeType === 3){
? ??????????var reg=/\{\{(.*)\}\}/;
? ??????????if(reg.test(node.nodeValue.trim())){
? ??????????????????var name=RegExp.$1;
? ? ? ? ? ? ? ? ? ? ?node.nodeValue=vm.data[name];
? ? ? ? ? ? ?}
? ??}
}
然后很重要的一步就是獲取到id為app元素節(jié)點下的所有節(jié)點惩琉,調(diào)用剛剛封裝好了的compile方法即可,那么如何來獲取到這所謂的所有節(jié)點呢?小伙伴們可能一下子就想到了節(jié)點屬性上有一個childNodes埂息,然后循環(huán)這里的每一項,如果該項存在著子節(jié)點的話技扼,可以遞歸調(diào)用該方法,emm嫩痰,聽起來很有道理的感覺剿吻,代碼如下圖所示。
但是這么運行起來的時候結果并沒有達到預期的效果串纺,問題出現(xiàn)在哪了呢丽旅?說實話,我也踩了一下這個坑纺棺,思考了一下才反應過來魔招,這主要是由于DOM映射導致的,我們可以試著打印出循環(huán)的結果五辽,可以發(fā)現(xiàn)只打印出了4次办斑,而并沒有將里面的7項都給輸出,至于DOM映射機制在本篇文章當中就不進行過多的介紹杆逗,詳情可百度或參考我的個人博客乡翅。
既然知道了是DOM映射導致的問題,那么又該如何去解決呢罪郊,其實很簡單蠕蚜,在存在DOM映射的情況下,每一次node.childNodes的長度都會減一悔橄,并且去除的這一個正好是之前數(shù)組的第一項靶累,故而我們只需要每一次拿到node.childNodes的第一項就可以了。
那么除了for循環(huán)實現(xiàn)方式以外癣疟,有沒有其它更好的實現(xiàn)方式呢挣柬,答案是有的,還是類似的邏輯睛挚,我們可以用while來代替for循環(huán)邪蛔,只要我們的node存在第一個子節(jié)點(firstChild)就可以了。
好了扎狱,到此為止侧到,咱們就實現(xiàn)了單向數(shù)據(jù)綁定的操作,下一篇咱們再深入去實現(xiàn)雙向數(shù)據(jù)綁定的騷操作吧淤击!