如果有問題歡迎指出兔毒,另外使用了一些常用的ES6語法。
首先看一下任務(wù)
這個(gè)任務(wù)沒要求實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)綁定甸箱,所以之前的發(fā)布-訂閱模式育叁、事件傳播機(jī)制就不用考慮了,只需要考慮渲染出數(shù)據(jù)就好芍殖。
從new一個(gè)Vue豪嗽,可以看出Vue是一個(gè)構(gòu)造函數(shù)。根據(jù)使用Vue的經(jīng)驗(yàn)豌骏,不需要手動(dòng)bootstrap龟梦,所以new的過程應(yīng)該有個(gè)啟動(dòng)。但是考慮到有些框架提供手動(dòng)啟動(dòng)(angular.bootstrap)窃躲,并且這個(gè)方法是公用的计贰,不用每個(gè)實(shí)例都創(chuàng)建一個(gè),所以把初始化的方法放在原型里蒂窒。
Vue接收兩個(gè)參數(shù)一個(gè)是Selector另一個(gè)是數(shù)據(jù)對(duì)象,根據(jù)Vue的使用經(jīng)驗(yàn)就是Selector是app的應(yīng)用范圍象迎,其中的特定格式的({{}}中)字符串會(huì)被Vue實(shí)例中data中的數(shù)據(jù)同名屬性的值替換恋技,這就是啟動(dòng)的方法做的事情。所以任務(wù)分解成兩個(gè)小任務(wù),<b>一個(gè)是在dom中找到指定的格式脱惰,其實(shí)就是搜索文本和替換;</b><b>另一個(gè)是在遍歷data中的屬性,把這些可能需要替換的屬性保存起來烦租;</b>
尋找dom中指定的字符串痴颊,通過正則去匹配,使用字符串的replace方法去替換。通過textContent這個(gè)HTML DOM Element對(duì)象的屬性,獲得dom節(jié)點(diǎn)內(nèi)的文本,但是這個(gè)有個(gè)問題就是設(shè)置 textContent 屬性绑嘹,會(huì)刪除所有子節(jié)點(diǎn)畅卓,并被替換為包含指定字符串的一個(gè)單獨(dú)的文本節(jié)點(diǎn)。所以要判斷到了dom樹的末端渗勘,才能使用价淌,不然會(huì)破壞dom結(jié)構(gòu)巷蚪。所以要用到遞歸和判斷。
子任務(wù)一:
// 判斷是否有textContent屬性
if (!('textContent' in document)) {
console.log('Please upgrade your browser!');
return
}
// 獲取app入口的dom節(jié)點(diǎn)
let appEntrance = document.getElementById(el.slice(1));
// 將入口元素內(nèi)部的符合的部分轉(zhuǎn)換成對(duì)應(yīng)的變量
function translate(entrance, reg, value) {
if (entrance instanceof HTMLElement) {
let children = entrance.childNodes;
let len = entrance.childNodes.length;
for (let i = 0; i < len; i++) {
if (children[i].childNodes.length > 0) {
translate(children[i], reg, value)
} else {
children[i].textContent = children[i].textContent.replace(reg, value);
}
}
} else {
console.log('Entrance is invalid!');
}
}
先在整個(gè)啟動(dòng)程序前判斷一下有沒有textContent屬性,如果沒有,直接退出,因?yàn)楹诵木褪沁@個(gè)方法,避免后面一次次判斷了运沦。
把dom中符合格式的內(nèi)容替換成指定的內(nèi)容的函數(shù)被我命名為translate篓叶,接收三個(gè)參數(shù)entrance、reg佩抹、value廊勃,分別是搜索入口、用來匹配的正則、替換成的值桑寨。先判斷一下入口是不是一個(gè)dom節(jié)點(diǎn)班套,凡是dom節(jié)點(diǎn)都繼承于HTMLElement對(duì)象。使用兩個(gè)局部變量來保存一下子節(jié)點(diǎn)和長(zhǎng)度晌砾,不然每次調(diào)用都會(huì)在dom中查找一遍陨晶。然后判斷如果有子節(jié)點(diǎn)則遞歸調(diào)用,直到末端,通過屬性獲得文本咧虎,通過正則替換符合格式的內(nèi)容苇瓣,然后再賦予屬性画切。至此其中一個(gè)任務(wù)完成了毫别。
子任務(wù)二:
// 遍歷屬性去替換
function walk(entrance, obj, name) {
if (entrance instanceof HTMLElement) {
if (obj !== null && typeof obj === 'object') {
let reg;
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] !== 'object') {
reg = name ? new RegExp(`{{${name}.${key}}}`, 'g') : new RegExp(`{{${key}}}`, 'g');
translate(entrance, reg, obj[key]);
} else {
walk(entrance, obj[key], name ? `${name}.${key}` : key);
}
}
}
}
} else {
console.log('Entrance is invalid!');
}
}
這個(gè)遍歷函數(shù)接收三個(gè)參數(shù),entrance、obj本鸣、name涮瞻,其中entrance是入口的dom節(jié)點(diǎn)、obj是要查找屬性的對(duì)象、name是父級(jí)對(duì)象的名字减宣,因?yàn)榛ɡㄌ?hào)里的是對(duì)象名稱加上屬性晓勇,所以需要記錄下祖先名稱堂飞。先判斷一下入口dom節(jié)點(diǎn)是不是合法,再判斷obj是否是對(duì)象绑咱,然后對(duì)obj遍歷绰筛。通過hasOwnProperty來排除繼承的屬性,如果屬性是對(duì)象還要遞歸調(diào)用描融,對(duì)每個(gè)非對(duì)象屬性使用tranlate屬性來查找替換dom中的內(nèi)容铝噩。``字符串中使用${}可以解析出中間變量的內(nèi)容。
感覺這樣實(shí)現(xiàn)復(fù)雜度有點(diǎn)高窿克,應(yīng)該有更好的方法骏庸。
求贊,求star……
源碼地址:https://github.com/rennaiqian/baiduTask/blob/master/two-way-bind-4/two-way-bind-4.html