實(shí)現(xiàn)單向數(shù)據(jù)綁定

在實(shí)現(xiàn)雙向數(shù)據(jù)綁定的之前,先來實(shí)現(xiàn)單向數(shù)據(jù)綁定,首先,我們的HTML結(jié)構(gòu)如下圖所示。

<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里面實(shí)現(xiàn)單向數(shù)據(jù)綁定了,不管怎么樣,我們就像Vue一樣,直接來創(chuàng)建個(gè)Vue實(shí)例化對(duì)象。

new Vue({

????el:"app",

????data:{

????????msg:"hello world",

????????test:"單向綁定"

????}

});

而此時(shí)根本就沒有Vue這個(gè)類,所以下一步直接來創(chuàng)建這個(gè)類,在這個(gè)類當(dāng)中,我們將傳遞過來的el屬性值賦值給id(該例中以id為例),并且也用一個(gè)data來保存?zhèn)鬟f過來的data信息。

function Vue(options){

????this.id=options.el;

? ??this.data=options.data;

}

好了,那么下一步的問題就是如何實(shí)現(xiàn)單向數(shù)據(jù)綁定的問題了,在Vue當(dāng)中,我們可以通過v-model這樣的屬性名或者{{}}的形式來進(jìn)行綁值操作,很顯然,我們是需要依次獲取到整個(gè)id為app標(biāo)簽下的所有node節(jié)點(diǎn),當(dāng)其是元素節(jié)點(diǎn)的時(shí)候,就要查看其屬性名是否含有v-model,如果有,根據(jù)其設(shè)置的value值對(duì)應(yīng)的去Vue實(shí)例化對(duì)象的data屬性中查找并賦值;當(dāng)其是文本節(jié)點(diǎn)的時(shí)候,就需要匹配{{}}里面的內(nèi)容,然后同上操作。

為了講解方便,就先來實(shí)現(xiàn)根據(jù)節(jié)點(diǎn)所屬類別來進(jìn)行賦值操作的方法,該方法需要兩個(gè)參數(shù),一個(gè)參數(shù)為當(dāng)前的節(jié)點(diǎn),一個(gè)為實(shí)例化的Vue對(duì)象。

function compile(node,vm){

? ??//當(dāng)node節(jié)點(diǎn)為元素節(jié)點(diǎn)時(shí)

? ??if(node.nodeType === 1){

? ??????var attr=node.attributes;

? ??????//遍歷當(dāng)前節(jié)點(diǎn)的所有屬性

? ??????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);

? ? ? ? ? ? ? }????

? ?????}

????}

? ??//當(dāng)node節(jié)點(diǎn)為文本節(jié)點(diǎn)時(shí)

? ??if(node.nodeType === 3){

? ??????????var reg=/\{\{(.*)\}\}/;

? ??????????if(reg.test(node.nodeValue.trim())){

? ??????????????????var name=RegExp.$1;

? ? ? ? ? ? ? ? ? ? ?node.nodeValue=vm.data[name];

? ? ? ? ? ? ?}

? ??}

}

然后很重要的一步就是獲取到id為app元素節(jié)點(diǎn)下的所有節(jié)點(diǎn),調(diào)用剛剛封裝好了的compile方法即可,那么如何來獲取到這所謂的所有節(jié)點(diǎn)呢?小伙伴們可能一下子就想到了節(jié)點(diǎn)屬性上有一個(gè)childNodes,然后循環(huán)這里的每一項(xiàng),如果該項(xiàng)存在著子節(jié)點(diǎn)的話,可以遞歸調(diào)用該方法,emm,聽起來很有道理的感覺,代碼如下圖所示。


但是這么運(yùn)行起來的時(shí)候結(jié)果并沒有達(dá)到預(yù)期的效果,問題出現(xiàn)在哪了呢?說實(shí)話,我也踩了一下這個(gè)坑,思考了一下才反應(yīng)過來,這主要是由于DOM映射導(dǎo)致的,我們可以試著打印出循環(huán)的結(jié)果,可以發(fā)現(xiàn)只打印出了4次,而并沒有將里面的7項(xiàng)都給輸出,至于DOM映射機(jī)制在本篇文章當(dāng)中就不進(jìn)行過多的介紹,詳情可百度或參考我的個(gè)人博客。

既然知道了是DOM映射導(dǎo)致的問題,那么又該如何去解決呢,其實(shí)很簡單,在存在DOM映射的情況下,每一次node.childNodes的長度都會(huì)減一,并且去除的這一個(gè)正好是之前數(shù)組的第一項(xiàng),故而我們只需要每一次拿到node.childNodes的第一項(xiàng)就可以了。


那么除了for循環(huán)實(shí)現(xiàn)方式以外,有沒有其它更好的實(shí)現(xiàn)方式呢,答案是有的,還是類似的邏輯,我們可以用while來代替for循環(huán),只要我們的node存在第一個(gè)子節(jié)點(diǎn)(firstChild)就可以了。


好了,到此為止,咱們就實(shí)現(xiàn)了單向數(shù)據(jù)綁定的操作,下一篇咱們再深入去實(shí)現(xiàn)雙向數(shù)據(jù)綁定的騷操作吧!



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 父親是屬雞的,給我的感覺就是愛碎碎念。 我小的時(shí)候,爸爸在鎮(zhèn)上的道班隊(duì)上班,那會(huì)因?yàn)閯傂?12國道,爸爸作為小班...
    健康才能幸福袁芳閱讀 260評(píng)論 0 2
  • 我時(shí)常在思考一個(gè)問題:到底是生活誘惑了生命?還是生命褻瀆了生活?遺憾的是,至今無果。 臺(tái)灣作...
    夢釗閱讀 354評(píng)論 0 0
  • 方法一:輸入法半角改全角, 輸入2次空格。 方法二: 方法三: 在開頭的時(shí)候,先輸入這個(gè),然后緊跟著輸入文本即可。...
    AsaGuo閱讀 524評(píng)論 0 0

友情鏈接更多精彩內(nèi)容