简单模板模式
概念介绍
简单模板模式(Simple template): 通过格式化字符串拼凑出视图避免创建视图时大量节点操作,优化内存开销。
创建模板
在实际的业务中如果我们需要进行前后台交互,或多或少会遇到需要把后台数据,绑定到我们通过js生成的html里,然后再展示到页面上的需求,比如现在我要生成如下样式并展示到页面上。
首先我们肯定会分析这个页面的结构然后去创建相应的节点并在页面中展示,比如像下面这样
//我们可以创建一个模板类的命名空间
var T=T||{};
//我们接着创建一个根节点,我们需要生成的模板会在这个节点下显示
T.root=document.getElementById('container');
//我们创建一个集合存储模板
T.TempFactory={
'listTemp':function(data){
//创建最外层的容器
var d=document.createElement("div"),
//接着创建下级的标题容器
h=document.createElement("h2"),
//标题下面的段落容器
p=document.createElement("p"),
//向标题容器中添加内容
ht=document.createTextNode(data.data.h2),
//向段落容器中添加内容
pt=document.createTextNode(data.data.p),
//创建列表容器
ul=document.createElement("ul"),
//获取数据中的li标签
ldata=data.data.li,
//依次是li元素,strong元素,span元素,填充strong内容,填充span内容
li,strong,span,t,c;
//如果数据里存在ID就给最外层容器赋值ID
data.id&&(d.id=data.id);
//向标题里追加内容
h.appendChild(ht);
//向段落里追加内容
p.appendChild(pt);
//把标题添加到最外层的容器里
d.appendChild(h);
//把段落添加到最外层的容器里
d.appendChild(p);
//循环添加数据中的列表
for (var i=0;i<ldata.length;i++) {
//创建li标签
li=document.createElement("li");
//创建strong标签
strong=document.createElement("strong");
//创建span标签
span=document.createElement("span");
//向strong标签中添加内容
t=document.createTextNode(ldata[i].strong);
//向span标签中添加内容
c=document.createTextNode(ldata[i].span);
//把内容追加进strong标签
strong.appendChild(t);
//把内容追加进span标签
span.appendChild(c);
//把strong标签追加进li标签
li.appendChild(strong);
//把span标签追加进li标签
li.appendChild(span);
//把li标签追加到ul标签下
ul.appendChild(li);
}
//像我们最外层的容器中添加李彪
d.appendChild(ul);
//最后把创建的模板插入到我们之前创建的根节点下
T.root.appendChild(d);
}
}
//增加初始化方法
T.init=function(data){
this.TempFactory[data.type](data);
}
好的我们创建好了模板试着模拟数据调用一下
var datas={id:"test",type:"listTemp",data:{h2:"标题",p:"内容",li:[{strong:"加粗列表内容",span:"列表内容"},{strong:"加粗列表内容2",span:"列表内容2"}]}}
T.init(datas);
好了,我们看到我们的功能实现了,但是我们发现我们创建一个这么简单页面就要创建这么多节点看上去相当复杂而且麻烦,那我们如何去优化呢?这个时候我们就可以去试着优化模板,来简化我们的操作,我们还可以用一些占位符代替模板中需要填充的内容,到时候利用正则我们可以把占位符替换成对应的内容。
优化模板
首先我们需要添加一个方法把占位符变成我们的内容
T.formateString=function(str,data){
return str.replace(/{{(w+)}}/g,function(match,key){
return typeof data[key]===undefined ? '' : data[key]
})
}
接着我们开始修改我们之前臃肿的模板
'listTemp':function(data){
var d=document.createElement("div"),
ul="",
ldata=data.data.li,
//前面的方式还是不变这里,我们把这个改成模板。用{{}}充当占位符
tpl=[
'<h2>{{h2}}</h2>','<p>{{p}}</p>','<p>{{ul}}</p>'
].join(''),
//这里也是一样的这里是ul里的标签
liTpl=[
'<li>','<strong>{{strong}}</strong>','<span>{{span}}</span>','</li>'
].join('');
data.id&&(d.id=data.id);
//遍历列表数据
for (var i=0;i<ldata.length;i++) {
//如果列表有数据
if (ldata[i].strong||ldata[i].span) {
//列表字符串追加一项列表项
ul+=T.formateString(liTpl,ldata[i]);
}
}
//填充列表数据数据
data.data.ul=ul;
//用我们的替换方法渲染模块并插入我们的外层容器中
d.innerHTML=T.formateString(tpl,data.data);
//绑定到根节点下
T.root.appendChild(d);
}
好了我们再来看看
var datas={id:"test",type:"listTemp",data:{h2:"标题",p:"内容",li:[{strong:"加粗列表内容",span:"列表内容"},{strong:"加粗列表内容2",span:"列表内容2"}]}}
T.init(datas);
经过我们的优化是不是减少了很对对页面中节点的操作,但是我们发现我们这个模板还有相似之处我们还可以接着优化。
再次优化模板
我们的模板虽然简化了很多,但是我们发现标签占位符的结构都很相似,那么我们就可以把他们提出来,再次优化
我们可以把公共的地方提取出来创建一个模板生成器
//模板生成器
T.view=function(name){
//如果参数是一个数组,则返回多行模板
if(Object.prototype.toString.call(name)==="[object Array]"){
//模板缓存器
var tpl='';
//遍历标识
for(var i=0;i<name.length;i++){
//模板缓存器追加模板
tpl+=arguments.callee(name[i]);
}
//返回最终模板
return tpl;
}else{
//返回建议模板
return '<'+name+'>{{'+name+'}}</'+name+'>';
}
}
我们在修改一下之前的模板
T.TempFactory={
'listTemp':function(data){
var d=document.createElement("div"),
ul="",
ldata=data.data.li,
//这里用我们的模板生成器修改一下
tpl=T.view(['h2','p','ul']),
liTpl=T.formateString(T.view('li'),{li:T.view(['strong','span'])});
data.id&&(d.id=data.id);
for (var i=0;i<ldata.length;i++) {
if (ldata[i].em||ldata[i].span) {
ul+=T.formateString(liTpl,ldata[i]);
}
}
data.data.ul=ul;
d.innerHTML=T.formateString(tpl,data.data);
T.root.appendChild(d);
}
}
我们在看看
var datas={id:"test",type:"listTemp",data:{h2:"标题",p:"内容",li:[{strong:"加粗列表内容",span:"列表内容"},{strong:"加粗列表内容2",span:"列表内容2"}]}}
T.init(datas);
总结
简单模板模式主要解决御用DOM操作创建视图时造成资源消耗大、性能底下、操作复杂等问题。用正则的方式去格式化字符串执行的性能高于DOM操作拼接视图的执行性能。
也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~
好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。
欢迎转载,转载请注明作者,原文出处。