为什么要使用模板引擎
DOM结构简单,完全可以使用DOM方法创建DOM树。$("<td></td").appendTo();
当页面比较复杂的时候,下面的程序中红色部分来自JSON中的数据:
<div class="feeds-item hasImg" id="item-702635">
<p class="feeds-item-pic">
<a href="http://gupowang.baijia.baidu.com/article/702635" target="_blank" >
<img src="http://d.hiphotos.baidu.com/news/crop%3D0%2C1%2C612%2C367%3Bw%3D638/sign=243504ed134c510fba8bb85a5d69091c/e1fe9925bc315c6097d9b1ca84b1cb1349547743.jpg"></a>
</p>
<h3>
<a href="http://gupowang.baijia.baidu.com/article/702635" target="_blank" mon="col=13&pn=2">Snap这款眼镜真能带来一场社交革命吗?</a>
</h3>
<p class="feeds-item-text1">
Snapchat母公司Snap在11月10日推出的一款智能眼镜——Spectacles,目前在美国亚马逊网站里的合作商户页面标价依然高达1599美元,...
</p>
<div class="feeds-item-info">
<p class="labels">
<span class="label">
<a class="labelnm" href="http://baijia.baidu.com/?tn=listarticle&labelid=142650" target="_blank">snap</a>
</span>
<span class="label">
<a class="labelnm" href="http://baijia.baidu.com/?tn=listarticle&labelid=24262" target="_blank">眼镜</a>
</span>
<span class="label">
<a class="labelnm" href="http://baijia.baidu.com/?tn=listarticle&labelid=26751" target="_blank">社交革命</a>
</span>
</p>
<a href="http://gupowang.baijia.baidu.com/" class="feeds-item-author" target="_blank">姑婆那些事儿</a> <i class="public-v"></i>
<span class="tm">10:14</span>
<span class="count">阅读(9)</span>
<a href="javascript:;" class="share-article"> <i class="i ishare"></i>
分享
<dl class="changeshare">
<dd class="sina"></dd>
<dd class="qzone"></dd>
<dd class="wechat"></dd>
</dl>
</a>
</div>
</div>
如果使用DOM方法创建上面的结构,太复杂了!不容易进行更改。此时最好的办法就是“模板引擎”。
模板引擎的原理
就是字符串的replace函数。
最简单的replace函数:
<script type="text/javascript"> ???var str = "我爱杨洋,杨洋很帅,杨洋很会唱歌"; ???str = str.replace(/杨洋/g,"李易峰"); ???alert(str);</script>
replace函数的第二个参数可以是函数:
???<script type="text/javascript"> ???????var str = "我爱杨洋,杨洋很帅,杨洋很会唱歌"; ???????str = str.replace(/杨洋/g,function(){ ???????????return "李易峰"; ???????}); ???????alert(str); ???</script>
分组捕获,可以使用$1来参与生成替换字符串,比如把人民币换成美元。
???<script type="text/javascript"> ???????var str = "我一共有100元,早饭10元,午饭20元,晚饭15元。"; ???????str = str.replace(/([\d]+)元/g,function(match,$1){ ???????????return $1 / 6.2 + "美元"; ???????}); ???????alert(str); ???</script>
模板原理:
???<script type="text/javascript"> ???????//模板字符串 ???????var str = "好{{xinqing}}啊,今天我买了{{dongxi}},花了{{qian}}元"; ???????//字典(数据) ???????var dictionary = { ???????????"xinqing" : "高兴", ???????????"dongxi" : "手机", ???????????"qian" : 1000 ???????} ???????//数据绑定 ???????str = str.replace(/{{(\w+)}}/g,function(match,$1){ ???????????return dictionary[$1]; ???????}); ???????//显示结果 ???????alert(str); ???</script>
模板一共要三步走:
① 准备模板字符串。所谓的模板字符串就是含有模板标记的字符串,模板标记可以任意设置。
② 准备字典(这个名字是前几年流行的,现在就单纯的叫做“数据”)
③ 数据绑定,其实很简单就是用字典的v去对用替换模板标记k的那个地方。
一般不使用自己开发的模板引擎解析程序,因为不好用,比如模板标记加上空格,就不能识别了。
一般使用underscore来进行模板操作。
???<script type="text/javascript" src="js/underscore-min.js"></script> ???<script type="text/javascript"> ???????//模板字符串 ???????var str = "好<%=xinqing%>啊,今天我买了<%=dongxi%>,花了<%=qian%>元"; ???????//准备编译函数,使用underscore提供的template函数,接受一个模板字符串,返回一个函数。 ???????var compiled = _.template(str); ???????//数据绑定 ???????var str2 = compiled({ ???????????"xinqing" : "高兴", ???????????"dongxi" : "手机", ???????????"qian" : 1000 ???????}); ???????alert(str2); ???</script>
使用underscore进行模板操作的时候:
① 准备模板字符串,模板标记不能任意执行,必须是<%=%>。其实underscore源码中可以自由更改。
② 生成一个编译函数,使用内置的_.template()函数,template就是模板的意思。这个函数接受一个字符串(就是刚才的模板字符串)当做参数,返回一个函数。
③ 数据绑定,直接调用刚才生成的compiled函数,把字典往里面扔,此时就能返回绑定之后的字符串。
模板引擎的使用
首先我们准备一个复杂JSON:
后台哥哥生成了JSON,他的工作就完成了,不管前端是如何进行数据可视化的。
然后进行界面的HTML、CSS开发,把重复的部分,放到
<script type="text/template"></script>
不一定一定是text/template,只要不是test/javascript就行了。浏览器认为遇见了一个陌生的语言,从而静默,不予处理,不报错。
把需要使用模板的地方,使用模板标记替换。注意,模板标记中的英语单词,必须要根据字典中的key来决定。
<script type="text/template" id="feeds_template"> ???<div class="feeds"> ???????<div class="pic"> ???????????<a href="<%= m_display_url %>"> ???????????????<img src="<%= m_image_url %>" ?/> ???????????</a> ???????</div> ???????<div class="feed_main"> ???????????<h3> ???????????????<a href="<%= m_display_url %>"> ???????????????????<%= m_title %> ???????????????</a> ???????????</h3> ???????????<p class="summary"> ???????????????<%= m_summary %> ???????????</p> ???????????<div class="info"> ???????????????<span class="writer"><%= m_writer_name %></span> ???????????????<span><img src="images/v.png" ?/></span> ???????????????<span class="time"><%= m_create_time %></span> ???????????????<span class="yuedu">阅读<b>(<%= hotcount %>)</b></span> ???????????</div> ???????</div> ???</div></script>
此时就可以书写程序:
<script type="text/javascript" src="js/jquery-1.12.3.min.js"></script><script type="text/javascript" src="js/underscore-min.js"></script><script type="text/javascript"> ???//得到模板字符串 ???var template_str = $("#feeds_template").html(); ???//生成编译函数 ???var compiled = _.template(template_str); ???//发出Ajax请求,请求字典 ???$.get("json/baijia0.txt",function(data){ ???????//转为obj对象 ???????dataobj = typeof data == "object" ? data : eval("(" + data + ")"); ???????//遍历数组,得到20本字典。分别数据绑定,分别上树 ???????_.each(dataobj.data.list , function(dictionary){ ???????????//数据绑定 ???????????var str = compiled(dictionary); ???????????//上树 ???????????$(str).appendTo(".main_news") ???????}); ???});</script>
模板修正
模板中存放的是 m_writer_account_type: "0" 或者"2"
此时我们要变为v图标是否显示,就可以写程序:
//发出Ajax请求,请求字典$.get("json/baijia0.txt",function(data){ ???//转为obj对象 ???dataobj = typeof data == "object" ? data : eval("(" + data + ")"); ???//遍历数组,得到20本字典。分别数据绑定,分别上树 ???_.each(dataobj.data.list , function(dictionary){ ???????//数据绑定 ???????var str = compiled(dictionary); ???????//把字符串变为DOM ???????var $dom = $(str); ???????//上树 ???????$dom.appendTo(".main_news") ???????//选择显示和隐藏这个v ???????if(dictionary.m_writer_account_type == "0"){ ???????????$dom.find(".v").show(); ???????}else{ ???????????$dom.find(".v").hide(); ???????} ???});});
有些时候我们甚至可以补充key:
_.each(dataobj.data.list , function(dictionary){ ???//模板修正 ???dictionary.biaoqian = "么么哒"; ???//数据绑定 ???var str = compiled(dictionary); ???//把字符串变为DOM ???var $dom = $(str); ???//上树 ???$dom.appendTo(".main_news") ???//选择显示和隐藏这个v ???if(dictionary.m_writer_account_type == "0"){ ???????$dom.find(".v").show(); ???}else{ ???????$dom.find(".v").hide(); ???}});
子模板
来看百度百家的实际应用,此时JSON里面又有一个数组,需要遍历:
需要生成:
<div class="feeds __web-inspector-hide-shortcut__"> ???<div class="pic"> ???????<a href="http://liukuang.baijia.baidu.com/article/702650"> ???????????????<img src="http://h.hiphotos.baidu.com/news/crop%3D0%2C1%2C590%2C354%3Bw%3D638/sign=bd98abbaad0f4bfb989fc4143e7f54c1/b3fb43166d224f4a1f3eb73600f790529822d174.jpg" alt=""> ???????????</a> ???</div> ???<div class="feed_main"> ???????<h3> ???????????????<a href="http://liukuang.baijia.baidu.com/article/702650"> ???????????????????从混战到三足鼎立,外卖O2O下一个谁先出局? ???????????????</a> ???????????</h3> ???????<p class="summary"> ???????????外卖O2O市场份额显示出:三强称霸整个市场的局面越来越明显。那么,从上半场的混战走向如今的三足鼎立,到了外卖O2O三国战的下半场,又将是怎样的格局? ???????</p> ???????<div class="info"> ???????????<span class="writer">刘旷</span> ???????????<span><img class="v" src="images/v.png" alt=""></span> ???????????<span class="time">10:25</span> ???????????<span class="yuedu">阅读<b>(642)</b></span> ???????????<span class="labels"><a href="http://baijia.baidu.com/?tn=listarticle&labelid=19240">外卖O2O</a><a href="http://baijia.baidu.com/?tn=listarticle&labelid=10595">市场</a> ???????????</span> ???????</div> ???</div></div>
此时方法1,就是DOM法:
// 发出Ajax请求,请求字典$.get("/json/baijia0.txt",function(data){ ???var dataobj = typeof data == "object" ? data : eval("(" + data + ")"); ???var list = dataobj.data.list; ???//each函数会遍历list数组,会让list中的每一项注入到函数中成为实参 ???_.each(list,function(dictionary){ ???????//数据绑定 ???????var feedStr = feed_compiled(dictionary); ???????//转为DOM元素 ???????var $dom = $(feedStr); ???????//上树 ???????$dom.appendTo(".main_news"); ???????//决定v是否显示 ???????if(dictionary.m_writer_account_type != "0"){ ???????????$dom.find(".v").hide(); ???????} ???????//上标签 ???????for(var i = 0 ; i < dictionary.m_label_names.length ; i++){ ???????????$("<a href=‘http://baijia.baidu.com/?tn=listarticle&labelid=" + dictionary.m_label_names[i].m_id + "‘>" + dictionary.m_label_names[i].m_name + "</a>").appendTo($dom.find("span.labels")); ???????} ???});});
方法2子模板,我们有了模板之后,就再也不要去拼接字符串了!
<script type="text/template" id="labels_template"> ???????<a href="http://baijia.baidu.com/?tn=listarticle&labelid=<%=m_id%>"><%= m_name %></a></script>
<script type="text/javascript"> ???// 得到模板字符串 ???var feed_template_str = $("#feed_template").html(); ???var labels_template_str = $("#labels_template").html(); ???// 模板编译函数 ???var feed_compiled = _.template(feed_template_str); ???var labels_compiled = _.template(labels_template_str); ???// 发出Ajax请求,请求字典 ???$.get("/json/baijia0.txt",function(data){ ???????var dataobj = typeof data == "object" ? data : eval("(" + data + ")"); ???????var list = dataobj.data.list; ???????//each函数会遍历list数组,会让list中的每一项注入到函数中成为实参 ???????_.each(list,function(dictionary){ ???????????//feed模板数据绑定 ???????????var feedStr = feed_compiled(dictionary); ???????????//转为DOM元素 ???????????var $dom = $(feedStr); ???????????//上树 ???????????$dom.appendTo(".main_news"); ???????????//决定v是否显示 ???????????if(dictionary.m_writer_account_type != "0"){ ???????????????$dom.find(".v").hide(); ???????????} ???????????//设置labels ???????????for(var i = 0 ; i < dictionary.m_label_names.length ; i++){ ???????????????var aStr = labels_compiled(dictionary.m_label_names[i]); ???????????????$dom.find("span.labels").append($(aStr)); ???????????} ???????}); ???});</script>
模板引擎原理及underscore.js使用
原文地址:https://www.cnblogs.com/-liujia/p/9352069.html