如果有這樣一種需求
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;
})
完美解決問題