百度前端學(xué)院動態(tài)數(shù)據(jù)綁定(四)及搜索替換文本

如果有問題歡迎指出,另外使用了一些常用的ES6語法。

首先看一下任務(wù)

動態(tài)數(shù)據(jù)綁定(四)

這個任務(wù)沒要求實(shí)現(xiàn)動態(tài)數(shù)據(jù)綁定,所以之前的發(fā)布-訂閱模式、事件傳播機(jī)制就不用考慮了,只需要考慮渲染出數(shù)據(jù)就好。

從new一個Vue,可以看出Vue是一個構(gòu)造函數(shù)。根據(jù)使用Vue的經(jīng)驗(yàn),不需要手動bootstrap,所以new的過程應(yīng)該有個啟動。但是考慮到有些框架提供手動啟動(angular.bootstrap),并且這個方法是公用的,不用每個實(shí)例都創(chuàng)建一個,所以把初始化的方法放在原型里。

Vue接收兩個參數(shù)一個是Selector另一個是數(shù)據(jù)對象,根據(jù)Vue的使用經(jīng)驗(yàn)就是Selector是app的應(yīng)用范圍,其中的特定格式的({{}}中)字符串會被Vue實(shí)例中data中的數(shù)據(jù)同名屬性的值替換,這就是啟動的方法做的事情。所以任務(wù)分解成兩個小任務(wù),<b>一個是在dom中找到指定的格式,其實(shí)就是搜索文本和替換;</b><b>另一個是在遍歷data中的屬性,把這些可能需要替換的屬性保存起來;</b>


尋找dom中指定的字符串,通過正則去匹配,使用字符串的replace方法去替換。通過textContent這個HTML DOM Element對象的屬性,獲得dom節(jié)點(diǎn)內(nèi)的文本,但是這個有個問題就是設(shè)置 textContent 屬性,會刪除所有子節(jié)點(diǎn),并被替換為包含指定字符串的一個單獨(dú)的文本節(jié)點(diǎn)。所以要判斷到了dom樹的末端,才能使用,不然會破壞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)換成對應(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!');
                }
            }

先在整個啟動程序前判斷一下有沒有textContent屬性,如果沒有,直接退出,因?yàn)楹诵木褪沁@個方法,避免后面一次次判斷了。

把dom中符合格式的內(nèi)容替換成指定的內(nèi)容的函數(shù)被我命名為translate,接收三個參數(shù)entrance、reg、value,分別是搜索入口、用來匹配的正則、替換成的值。先判斷一下入口是不是一個dom節(jié)點(diǎn),凡是dom節(jié)點(diǎn)都繼承于HTMLElement對象。使用兩個局部變量來保存一下子節(jié)點(diǎn)和長度,不然每次調(diào)用都會在dom中查找一遍。然后判斷如果有子節(jié)點(diǎn)則遞歸調(diào)用,直到末端,通過屬性獲得文本,通過正則替換符合格式的內(nèi)容,然后再賦予屬性。至此其中一個任務(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!');
                }
            }

這個遍歷函數(shù)接收三個參數(shù),entrance、obj、name,其中entrance是入口的dom節(jié)點(diǎn)、obj是要查找屬性的對象、name是父級對象的名字,因?yàn)榛ɡㄌ柪锏氖菍ο竺Q加上屬性,所以需要記錄下祖先名稱。先判斷一下入口dom節(jié)點(diǎn)是不是合法,再判斷obj是否是對象,然后對obj遍歷。通過hasOwnProperty來排除繼承的屬性,如果屬性是對象還要遞歸調(diào)用,對每個非對象屬性使用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

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

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

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