手寫一個簡單模板引擎總結

如果有這樣一種需求

var data = {
    name: 'ruoyu',
    addr: 'Hunger Valley'
};
var tpl = 'Hello, my name is  {{name}}. I am in {{addr}}.';

要求你把tpl字符串里形如{{}}的字符串替換成data對象里面對應的key,我們怎么搞

我們首先分析形如{{}}字符串的規(guī)律,然后定義一個正則來匹配它。通過分析,我們知道{{}}里面是一個變量。

那么他就滿足變量的一般規(guī)則:

1.變量必須以字母、下劃線或者$開頭,但是不能以數字開頭

2.變量第一個符號后面可以接字母、數字、下劃線、或者.

我們依照這兩條規(guī)則來定義一個正則

var reg=/{{[a-zA-Z_$][a-zA-Z0-9_.]*}}/g;

我們可以使用字符串的replace方法來匹配正則,達到字符串替換目的

var newStr = tpl.replace(reg,'123')
console.log(newStr)

瀏覽器輸出結果:

Hello, my name is 123. I am in 123.

這樣的替換方式功能太弱,他只能把匹配到的字符串替換成相同的內容,而我們的目的是把{{name}}替換成data[name],把{{addr}}替換成data[addr]。

如果你去看replace()方法的api,就會發(fā)現它的第二個參數可以是一個函數。

var newStr = tpl.replace(reg,function(raw,key,offset,string){
})

function的第一個參數raw是正則匹配到的內容{{name}}、{{addr}}

如果把reg寫成這樣

var reg=/{{([a-zA-Z_$][a-zA-Z0-9_.]*)}}/g;

相比上面,多了一對括號,也就是給reg添加一個子表達式,這樣function的第二個參數就起作用了,key的意思是reg的第一個子表達式匹配到的內容name、addr

這樣就可以滿足目的

var newStr = tpl.replace(reg,function(raw,key,offset,string){
    return data[key]||raw;
})

但是,還有一個問題需要解決,假如data這樣寫

var data={
    name: 'ruoyu',
    addr: 'Hunger Valley',
    friend: {
        name: 'hunger',
        car: {
            color: 'white'
        }
    }
}
var tpl = 'Hello, my name is  {{name}}. I am in {{age}},I have a friend {{friend.name}},he has a {{friend.car.color}} car'

這樣使用上面的規(guī)則就匹配不到了,因為data對象里沒有名字是friend.name和friend.car.color的key,我們可以巧妙的利用數組的shift()方法來解決這個問題

先把匹配到的data里面不存在的key變成一個數組

var newStr = tpl.replace(reg,function(raw,key,offset,string){
    var paths=key.split('.');
    var lookup=data;
    while(paths.length>0){
        lookup=lookup[paths.shift()];
    }
})

數組的shift()方法的作用是刪除并返回數組的第一個元素,假如匹配到的key是friend.car.color,那么paths=['friend','car','color'];paths.length=3>0,進入第一次循環(huán):paths.shift()返回friend,paths=['car','color'],lookup=data[friend]={name:'hunger',car:{color:'white'}}

這樣反復進行while循環(huán),直到paths里面什么都沒有的時候,這時的lookup就是我們需要的color了。

var newStr = tpl.replace(reg,function(raw,key,offset,string){
    var paths=key.split('.');
    var lookup=data;
    while(paths.length>0){
        lookup=lookup[paths.shift()];
    }
    return lookup||raw;
})

完美解決問題

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容