方案一 遍历
方案二 模板引擎
- 核心需求:写出这个字符串
var li = '<li>' + songs[i].name + ' - ' + songs[i].singer + '</li>' - 优化方案:使用函数格式化
var li = stringFormat('<li>{0} - {1}</li>', songs[i].name, songs[i].singer) - 如何实现:做出一个格式化字符串的工具
stringFormat
其他语言提供了string.format()函数用来生成具有特定格式的字符串,
不但是强大的字符串输出工具,还使得产生的长字符串可读性大大提高了.
这个函数接收第一个参数是string,其中{0}代表后传入的第一个变量,依次类推。
函数
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){} 它的参数是[形参 , 实参]
形参 str = '<li>{0} - {1}</li>'
实参 params = ['刚刚好','薛之谦'] 即【第0个替换的变量,第1个替换的变量】
所以
第0个匹配到的字符串是{0},第0个替换的变量是'刚刚好'
△1-6 的作用就是 {0} = '刚刚好'
△regex 的作用就是找出 {0}
△4-6 的作用就是找出 '刚刚好'
总结
△1-6 的作用就是 找出str中第n个被替换的字符串,用params[n]来替换它
△regex 的作用就是找出 被替换的字符串
△4-6 的作用就是找出 params[n]
步骤
-
1 定义一个数组params,取除str之外的所有参数(用来储存变量)
* .slice()可以返回数组中指定范围的元素
* 由于传入的参数是不确定的,所以需要用arguments来取
* 返回的是arguments数组从除第一项以外的所有项 -
2 使用正则找到"{n}"形式的字符串
* \d+ 表示1个或多个数字
* { } 表示{ }
* ( ) 表示分组,作用是取出{}里面的值
* / /g 表示global(全部)作用是打开全局匹配 -
3 然后将整个字符串中的
{n}这种字符串
替换为func返回值
* .replace() 第一个参数是目标,第二个参数用来替换目标 -
4 将
作为replace第二个参数的
函数打印出arguments
//console 发现2个对象,4个参数
[objectArguments]{ 对象1
0:"{0}", 第一个参数:匹配到字符串 {0}
1:"0", 第二个参数:拿到{}里面的内容0
2:4, 第三个参数:从第4个字符开始匹配到
3:"<li>{0} - {1}</li>" 第四个参数:整个字符串
}
[objectArguments]{ 对象2
0:"{1}", 第一个参数:匹配到字符串 {1}
1:"1", 第二个参数:拿到{}里面的内容1
2:10, 第三个参数:从第10个字符开始匹配到
3:"<li>{0} - {1}</li>" 第四个参数:整个字符串
}
可以发现第二个参数
是 匹配到的字符串的位置
这个位置对应了 替换的变量 的位置 -
5 得到这个位置
使用arguments[1]来取出此对象的第二个参数
-
6 返回 替换值
regex 的作用 找出 {0}
匿名函数的作用 得到 params[n]
arguments[1]的作用 找出 n
stringFormat的作用 {n} = params[n] -
升级方案:比字符串格式化的功能更强大
模板引擎
stringFormat 只能做到 1v1 的改变,每次输入一组值改变一个li
模板引擎 template(string,data) 只需要传入字符串和数据,就可以依次替换所有变量
举个例子先写一个简单的模板引擎
需求
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.函数 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使用正则找到
需要被替换的字符串
捕获所有以<%开头,以%>结尾的片段
* / /g 表示global(全部)作用是打开全局匹配
* <% %> 表示找出这个符号里面的字符串
* ( ) 表示分组(单独拿出来用)
* [ ]+? 表示一个集合,表示一个以上,表示可以为空
* ^%> 表示不能有%>这种符号(^在[]中表示非) -
2 如果在string中找到
需要被替换的字符串
先给match赋值为regex.exec(tpl)
* .exec()
这个方法遍历正则,每次只作一次匹配
如果正则无g,无限次匹配到第一个字符串;
如果正则加g,依次匹配每个字符串,直到结束返回null,然后从头开始;再作为while的判断条件 如果match = null,说明没匹配到字符串,结束! 如果match != null,说明匹配到了字符串,执行{...}; 结合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请在正则加全局谢谢
这样就初步实现了一个简单的模板引擎
复杂版!!待续...
目标:
<%this.name
%> => .call(data
)
思路:
把函数用<% %>包裹成字符串
使用正则把字符串中的<%函数%>匹配出来
放进一个 ''空字符串
or []空数组
拼接出函数
把字符串放在页面上,运行的时候调用函数
Tips:
dom节点类型
element
text
fragment内存中的虚拟对象,默认不被放在页面上
命名规则
表示string var div = <div></div>
表示DOM对象 var elDiv = document.createElement('div')
表示JQuery对象 var $Div = $('div')
文本API
.textContent H5标准写法 太长
.innerHtml 支持IE但有脚本注入风险
.innerText 兼容广无副作用-----------推荐使用
形参作用
1 影响函数的length属性,一个函数的length就是形参的个数
2 相当于给函数的第一个参数取名 var string = arguments[0]
调用arguments
由于它是 伪数组,不可以用数组的方法
这样调用 [].slice.call(arguments,1) 相当于 arguments.slice(1)
这种方式 先借用一个空数组的方法,后调用.call()把数组的this改成arguments
这样一来 就把数组的方法绑定到arguments身上了
声明函数的形式
* function xx(){ console.log(1) }
* var xx = function (){console.log(2) }
* var func = new function('参数','函数体') 相当于
var func = function(x){console.log(3)} 此方法 用字符串创建一个函数
网友评论