需求:用JS渲染一個 可以動態(tài)插入內(nèi)容的 歌曲列表
方案一 遍歷
方案二 模板引擎
- 核心需求:寫出這個字符串
var li = '<li>' + songs[i].name + ' - ' + songs[i].singer + '</li>' - 優(yōu)化方案:使用函數(shù)格式化
var li = stringFormat('<li>{0} - {1}</li>', songs[i].name, songs[i].singer) - 如何實現(xiàn):做出一個格式化字符串的工具
stringFormat
其他語言提供了string.format()函數(shù)用來生成具有特定格式的字符串,
不但是強大的字符串輸出工具,還使得產(chǎn)生的長字符串可讀性大大提高了.
這個函數(shù)接收第一個參數(shù)是string,其中{0}代表后傳入的第一個變量,依次類推。
函數(shù)
function stringFormat(str){
var params = [].slice.call(arguments,1); 1
var regex =/{(\d+)}/g; 2
str = str.replace(regex,function(){ 3
console.log(arguments); 4
var index = arguments[1]; 5
return params[index]; 6
})
}
var tpl = '<li>{0} - {1}</li>';
var result = stringFormat(tpl,'剛剛好','薛之謙');
分析
function stringFormat(str){}
var str = '<li>{0} - {1}</li>';
var result = stringFormat(str,'剛剛好','薛之謙');
因為
*function stringFormat(str){} 它的參數(shù)是[形參 , 實參]
形參 str = '<li>{0} - {1}</li>'
實參 params = ['剛剛好','薛之謙'] 即【第0個替換的變量,第1個替換的變量】
所以
第0個匹配到的字符串是{0},第0個替換的變量是'剛剛好'
△1-6 的作用就是 {0} = '剛剛好'
△regex 的作用就是找出 {0}
△4-6 的作用就是找出 '剛剛好'
總結(jié)
△1-6 的作用就是 找出str中第n個被替換的字符串,用params[n]來替換它
△regex 的作用就是找出 被替換的字符串
△4-6 的作用就是找出 params[n]
步驟
1 定義一個數(shù)組params,取除str之外的所有參數(shù)(用來儲存變量)
* .slice()可以返回數(shù)組中指定范圍的元素
* 由于傳入的參數(shù)是不確定的,所以需要用arguments來取
* 返回的是arguments數(shù)組從除第一項以外的所有項2 使用正則找到"{n}"形式的字符串
* \d+ 表示1個或多個數(shù)字
* { } 表示{ }
* ( ) 表示分組,作用是取出{}里面的值
* / /g 表示global(全部)作用是打開全局匹配3 然后將整個字符串中的
{n}這種字符串替換為func返回值
* .replace() 第一個參數(shù)是目標,第二個參數(shù)用來替換目標4 將
作為replace第二個參數(shù)的函數(shù)打印出arguments
//console 發(fā)現(xiàn)2個對象,4個參數(shù)
[objectArguments]{ 對象1
0:"{0}", 第一個參數(shù):匹配到字符串 {0}
1:"0", 第二個參數(shù):拿到{}里面的內(nèi)容0
2:4, 第三個參數(shù):從第4個字符開始匹配到
3:"<li>{0} - {1}</li>" 第四個參數(shù):整個字符串
}
[objectArguments]{ 對象2
0:"{1}", 第一個參數(shù):匹配到字符串 {1}
1:"1", 第二個參數(shù):拿到{}里面的內(nèi)容1
2:10, 第三個參數(shù):從第10個字符開始匹配到
3:"<li>{0} - {1}</li>" 第四個參數(shù):整個字符串
}
可以發(fā)現(xiàn)第二個參數(shù)是 匹配到的字符串的位置
這個位置對應了 替換的變量 的位置5 得到這個位置
使用arguments[1]來取出此對象的第二個參數(shù)6 返回 替換值
regex 的作用 找出 {0}
匿名函數(shù)的作用 得到 params[n]
arguments[1]的作用 找出 n
stringFormat的作用 {n} = params[n]-
升級方案:比字符串格式化的功能更強大
模板引擎
stringFormat 只能做到 1v1 的改變,每次輸入一組值改變一個li
模板引擎 template(string,data) 只需要傳入字符串和數(shù)據(jù),就可以依次替換所有變量
舉個例子先寫一個簡單的模板引擎
需求
var template = '<p>Hello, my name is <%name%>. I'm <%age%> years old.</p>';
var data = {
name: "Krasimir",
age: 29
}
console.log(TemplateEngine(template, data));
// Hello, my name is Krasimir. I'm 29 years old.函數(shù) var TemplateEngine = function(tpl, data) { var regex =/<%([^%>]+ )?%>/g; 1 有誤 while(match = regex.exec(tpl)) { 2 console.log(match); 3 tpl = tpl.replace(match[0], data[match[1]]); 4 } return tpl; 5 }
步驟
1使用正則找到
需要被替換的字符串
捕獲所有以<%開頭,以%>結(jié)尾的片段
* / /g 表示global(全部)作用是打開全局匹配
* <% %> 表示找出這個符號里面的字符串
* ( ) 表示分組(單獨拿出來用)
* [ ]+? 表示一個集合,表示一個以上,表示可以為空
* ^%> 表示不能有%>這種符號(^在[]中表示非)-
2 如果在string中找到
需要被替換的字符串
先給match賦值為regex.exec(tpl)
* .exec()
這個方法遍歷正則,每次只作一次匹配
如果正則無g,無限次匹配到第一個字符串;
如果正則加g,依次匹配每個字符串,直到結(jié)束返回null,然后從頭開始;再作為while的判斷條件 如果match = null,說明沒匹配到字符串,結(jié)束! 如果match != null,說明匹配到了字符串,執(zhí)行{...}; 結(jié)合1和2,在string中匹配到3個字符串 for (var i=0; i<songs.length; i++) { songs[i].name songs[i].singer } 3 打印出match
[
"<%name%>", 匹配項
" name ", ( )
index: 21,
input:
"<p>Hello, my name is <%name%>. I'm <%age%> years old.</p>"
]4 把
需要被替換的字符串替換為data
* .replace(a,b)
用b替換第一個a,如果要替換所有的a請在正則加全局謝謝
這樣就初步實現(xiàn)了一個簡單的模板引擎
復雜版?。〈m(xù)...
目標:
<%this.name%> => .call(data)
思路:
把函數(shù)用<% %>包裹成字符串
使用正則把字符串中的<%函數(shù)%>匹配出來
放進一個 ''空字符串 or []空數(shù)組 拼接出函數(shù)
把字符串放在頁面上,運行的時候調(diào)用函數(shù)
Tips:
dom節(jié)點類型
element
text
fragment內(nèi)存中的虛擬對象,默認不被放在頁面上
命名規(guī)則
表示string var div = <div></div>
表示DOM對象 var elDiv = document.createElement('div')
表示JQuery對象 var $Div = $('div')
文本API
.textContent H5標準寫法 太長
.innerHtml 支持IE但有腳本注入風險
.innerText 兼容廣無副作用-----------推薦使用
形參作用
1 影響函數(shù)的length屬性,一個函數(shù)的length就是形參的個數(shù)
2 相當于給函數(shù)的第一個參數(shù)取名 var string = arguments[0]
調(diào)用arguments
由于它是 偽數(shù)組,不可以用數(shù)組的方法
這樣調(diào)用 [].slice.call(arguments,1) 相當于 arguments.slice(1)
這種方式 先借用一個空數(shù)組的方法,后調(diào)用.call()把數(shù)組的this改成arguments
這樣一來 就把數(shù)組的方法綁定到arguments身上了
聲明函數(shù)的形式
* function xx(){ console.log(1) }
* var xx = function (){console.log(2) }
* var func = new function('參數(shù)','函數(shù)體') 相當于
var func = function(x){console.log(3)} 此方法 用字符串創(chuàng)建一個函數(shù)