摘要:更好的方案模板分离原则模板分离原则将定义模板的那一部分,与的代码逻辑分离开来,让代码更加优雅且利于维护。
引言
在前端开发中,经常需要动态添加一些元素到页面上。那么如何通过一些技巧,优化动态创建页面元素的方式,使得代码更加优雅,并且更易于维护呢?接下来我们通过研究一些实例,一步步地找出最优方案。
这篇文章尽量写得思路清晰且通俗易懂,由浅入深为刚入门前端的新手们带来一些思路和启发。
老手们也可以顺着看下去,当做复习一次。亦或者直接跳到后半部分,去看稍微深入一点的模板数据替换示例,一起交流交流哦。
由于DOM和HTML会存在一定的歧义,所以为了区别开来,文章中这两个术语的意思分别是:
DOM :专指文档对象,是在JS上以对象的形式存在的。
HTML:专指HTML文本,是一连串字符的集合。
实例一:如何动态添加元素到页面中话不多说,我们先来思考一下最基本的问题,如何用JS动态添加元素到页面中去呢?
假设在点击“添加一个乘客”按钮的时候,需要JS动态创建出一个新的输入框来填写姓名:
乘客列表:
从上面可以看出,要实现这个功能,我们需要处理的HTML片段是:
勉强的方案:手动复制粘贴HTML拼接成JS字符串乘客姓名:
那么我们先来看看传统的做法是这样子的:
先直接手动复制粘贴HTML拼接成JS字符串,然后再插入到表单中。
$(".create-passenger").on("click", function() { // 先直接手动复制粘贴HTML拼接成JS字符串 var html = "点评&分析" + " 乘客姓名:" + ""; // 然后再插入到表单中 $(".form").append(html); });
这是种偷懒的实现方式,在部分中小型网站、教科书上,最常见到它的身影。
在开发时的时候,某些情况下使用这种方案,的确可能会比较快速,直接复制粘贴HTML拼成JS字符串就可以了。
但满足这样的条件必须是:
要拼接的HTML字符串很短;
页面结构已经很稳定,能保证以后不会需要作出修改;
页面HMTL和JS的代码量都不多,或者已经直接把JS写在页面上了,所以即使设计不合理也能比较容易查看和维护。
问题&思考没有做好HTML和JS的分离,脚本强烈耦合了HTML,不妥不妥。
要是后期页面上的HTML有了改动,必须同时记得去找出相关的脚本文件,在JS代码中搜索并修改里面写死的HTML字符串才行。
换个角度再想一想,如果插入的HTML很复杂,有几百行的话。要在JS脚本中手动拼接庞大的字符串,是件非常的麻烦事情,还十分容易出差错。
更好的方案:模板分离原则一、利用页面上现有的DOM元素作为模板模板分离原则:将定义模板的那一部分,与JS的代码逻辑分离开来,让代码更加优雅且利于维护。
通过分析页面我们可以知道,表单初始的时候是至少会存在一个乘客输入项的。
所以我们可以复制表单上第一个乘客的DOM来作为模板:
$(".create-passenger").on("click", function() { // 复制第一个乘客的DOM作为模板 var template = $(".form .form-group:first-child").clone(); // 将DOM模板插入到表单中,形成新的一行 $(".form").append(template); });注意点&细节解析
实例中用了jquery的clone()方法,可以复制整个jquery包装过的DOM对象(不包括对象绑定的事件,如果要连事件也一起复制的话,可以加个参数clone(true)哦)。
有时候复制过来的DOM对象有可能不是最原始的状态,所以记得要初始化一下。例如有像input这样的输入项,要记得把value的值先初始化哦template.find("input").val("")。
二、在隐藏的标签中定义模板如果页面本来就没有相关的DOM,这时候可以手动新建一个隐藏的
接下来用JS去取这个元素的内容作为模板:
var template = $("#passenger-template > div").clone();注意点&细节解析
用一个标签来包裹模板的理由,
一是取模板的时候可以很方便,直接clone()或者html()就可以了;
二是为了更好地分类和规范。例如定义模板时,要求大家都用同一种标签和CSS类: 当然不一定去用 标签内的type="text/html",它能告诉浏览器这个标签里面的内容不是JS脚本,可以直接忽略不用去解析。这样浏览器就不会报错了。 还有一点是这时候就不能直接使用clone()了哦,因为标签里面的内容不是DOM对象,而是字符串类型的HTML片段。 所以记得要通过html()方法获取我们字符串形式的模板: JS和HTML做到了完全的解耦,十分利于后期的修改和维护。 脚本上没有了多余的代码,我们在开发的时候,只需关注业务逻辑了。 不用再去手动复制粘贴HTML来拼接JS字符串,写HTML比拼JS字符串要来的轻松,而且不容易出错。所以是一个明智之举,也算是有技巧地偷懒。 如果复制页面现有的DOM作为模板的话,可以完全脱离后期需要维护模板的限制。以后即使页面有修改了,JS这个“添加一个乘客”的功能,也一样能正常工作,适应性极强。 我们继续以前面的主题展开研究。不过这次的重点,是探究几种添加数据的实现方式,一步步找出最佳的方案。 新增的需求是这样的:如果想把特定的乘客信息,添加到新增的页面元素中,那样该怎么办呢? 下面将集中讲一下,改如何生成带有指定乘客信息的HTML片段,也就是这个get_passenger_html()的内部实现方式。 这个也是最传统的数据跟HTML字符串拼接的的方式,没有用到模板,脚本上会存在冗长的HTML字符串拼接代码。 这种做法没办法使用之前提到的模板技术,后期维护难是一个重大问题。 数据多一点或者html复杂一点,手动拼接字符串耗费精力、容易出错的弊端就会越来越显现。 能不能先定义好模板,然后再做数据插入的操作呢?这样就可以将模板定义和数据操作分离开来了,跟JS的字符串拼接Say good bye啦。 下面展示两种分离数据操作和模板定义的实现方式: 如果要插入的数据刚好是在某个标签或属性内,可以使用操作DOM对象的方式来插入数据: 如果模板不是clone()得来的,要先用$(html)将HTML字符串转成DOM对象,然后才能用find()去找到对应的DOM节点来操作哦。 html()方法只能获取子元素的HTML字符串,要获取包括自己的HTML字符串的话,要去读取outerHTML属性,这是个DOM对象原生的属性,所以要用prop()才能获取得到哦。 第一步先安照前面讲到的模板分离原则,定义了一个模板。在定义这个模板的时候,顺带添加一些带有特殊含义的占位符:{name}和{tel}。var template = $("#passenger-template").html(); // 获取的是字符串,不是DOM对象
模板分离原则的好处
$.ajax({
url: "/getPassengers", // 后台获取所有乘客的信息
success: function(passengers) {
var html = ""; // 储存要插入到页面的HTML片段
var len = passengers.length;
for (var i = 0; i < len; i++) {
// 获取带有该乘客信息的HTML片段
html += get_passenger_html(passengers[i]); // 后面将详细讲这个函数的实现方式
}
$(".form").append(html);
}
});
function get_passenger_html(passenger) {
var html = "";
html += "
点评&分析
function get_passenger_html(passenger) {
var html = $("#passenger-template").html(); // 获取HTML字符串模板
var dom = $(html); // 先即将HTML字符转成DOM对象
dom.find(".name").html(passenger.name); // 找到存放乘客姓名的DOM节点并插入数据
dom.find(".tel").html(passenger.tel); // 找到存放乘客电话的DOM节点并插入数据
// 把处理完毕的DOM转回HTML字符串并返回
return dom.prop("outerHTML");
}
注意点&细节解析