摘要:更好的方案模板分離原則模板分離原則將定義模板的那一部分,與的代碼邏輯分離開來,讓代碼更加優(yōu)雅且利于維護。
引言
在前端開發(fā)中,經常需要動態(tài)添加一些元素到頁面上。那么如何通過一些技巧,優(yōu)化動態(tài)創(chuàng)建頁面元素的方式,使得代碼更加優(yōu)雅,并且更易于維護呢?接下來我們通過研究一些實例,一步步地找出最優(yōu)方案。
這篇文章盡量寫得思路清晰且通俗易懂,由淺入深為剛入門前端的新手們帶來一些思路和啟發(fā)。
老手們也可以順著看下去,當做復習一次。亦或者直接跳到后半部分,去看稍微深入一點的模板數據替換示例,一起交流交流哦。
由于DOM和HTML會存在一定的歧義,所以為了區(qū)別開來,文章中這兩個術語的意思分別是:
DOM :專指文檔對象,是在JS上以對象的形式存在的。
HTML:專指HTML文本,是一連串字符的集合。
實例一:如何動態(tài)添加元素到頁面中話不多說,我們先來思考一下最基本的問題,如何用JS動態(tài)添加元素到頁面中去呢?
假設在點擊“添加一個乘客”按鈕的時候,需要JS動態(tài)創(chuàng)建出一個新的輸入框來填寫姓名:
乘客列表:
從上面可以看出,要實現(xiàn)這個功能,我們需要處理的HTML片段是:
勉強的方案:手動復制粘貼HTML拼接成JS字符串乘客姓名:
那么我們先來看看傳統(tǒng)的做法是這樣子的:
先直接手動復制粘貼HTML拼接成JS字符串,然后再插入到表單中。
$(".create-passenger").on("click", function() { // 先直接手動復制粘貼HTML拼接成JS字符串 var html = "點評&分析" + " 乘客姓名:" + ""; // 然后再插入到表單中 $(".form").append(html); });
這是種偷懶的實現(xiàn)方式,在部分中小型網站、教科書上,最常見到它的身影。
在開發(fā)時的時候,某些情況下使用這種方案,的確可能會比較快速,直接復制粘貼HTML拼成JS字符串就可以了。
但滿足這樣的條件必須是:
要拼接的HTML字符串很短;
頁面結構已經很穩(wěn)定,能保證以后不會需要作出修改;
頁面HMTL和JS的代碼量都不多,或者已經直接把JS寫在頁面上了,所以即使設計不合理也能比較容易查看和維護。
問題&思考沒有做好HTML和JS的分離,腳本強烈耦合了HTML,不妥不妥。
要是后期頁面上的HTML有了改動,必須同時記得去找出相關的腳本文件,在JS代碼中搜索并修改里面寫死的HTML字符串才行。
換個角度再想一想,如果插入的HTML很復雜,有幾百行的話。要在JS腳本中手動拼接龐大的字符串,是件非常的麻煩事情,還十分容易出差錯。
更好的方案:模板分離原則一、利用頁面上現(xiàn)有的DOM元素作為模板模板分離原則:將定義模板的那一部分,與JS的代碼邏輯分離開來,讓代碼更加優(yōu)雅且利于維護。
通過分析頁面我們可以知道,表單初始的時候是至少會存在一個乘客輸入項的。
所以我們可以復制表單上第一個乘客的DOM來作為模板:
$(".create-passenger").on("click", function() { // 復制第一個乘客的DOM作為模板 var template = $(".form .form-group:first-child").clone(); // 將DOM模板插入到表單中,形成新的一行 $(".form").append(template); });注意點&細節(jié)解析
實例中用了jquery的clone()方法,可以復制整個jquery包裝過的DOM對象(不包括對象綁定的事件,如果要連事件也一起復制的話,可以加個參數clone(true)哦)。
有時候復制過來的DOM對象有可能不是最原始的狀態(tài),所以記得要初始化一下。例如有像input這樣的輸入項,要記得把value的值先初始化哦template.find("input").val("")。
二、在隱藏的標簽中定義模板如果頁面本來就沒有相關的DOM,這時候可以手動新建一個隱藏的
接下來用JS去取這個元素的內容作為模板:
var template = $("#passenger-template > div").clone();注意點&細節(jié)解析
用一個標簽來包裹模板的理由,
一是取模板的時候可以很方便,直接clone()或者html()就可以了;
二是為了更好地分類和規(guī)范。例如定義模板時,要求大家都用同一種標簽和CSS類: 當然不一定去用 標簽內的type="text/html",它能告訴瀏覽器這個標簽里面的內容不是JS腳本,可以直接忽略不用去解析。這樣瀏覽器就不會報錯了。 還有一點是這時候就不能直接使用clone()了哦,因為標簽里面的內容不是DOM對象,而是字符串類型的HTML片段。 所以記得要通過html()方法獲取我們字符串形式的模板: JS和HTML做到了完全的解耦,十分利于后期的修改和維護。 腳本上沒有了多余的代碼,我們在開發(fā)的時候,只需關注業(yè)務邏輯了。 不用再去手動復制粘貼HTML來拼接JS字符串,寫HTML比拼JS字符串要來的輕松,而且不容易出錯。所以是一個明智之舉,也算是有技巧地偷懶。 如果復制頁面現(xiàn)有的DOM作為模板的話,可以完全脫離后期需要維護模板的限制。以后即使頁面有修改了,JS這個“添加一個乘客”的功能,也一樣能正常工作,適應性極強。 我們繼續(xù)以前面的主題展開研究。不過這次的重點,是探究幾種添加數據的實現(xiàn)方式,一步步找出最佳的方案。 新增的需求是這樣的:如果想把特定的乘客信息,添加到新增的頁面元素中,那樣該怎么辦呢? 下面將集中講一下,改如何生成帶有指定乘客信息的HTML片段,也就是這個get_passenger_html()的內部實現(xiàn)方式。 這個也是最傳統(tǒng)的數據跟HTML字符串拼接的的方式,沒有用到模板,腳本上會存在冗長的HTML字符串拼接代碼。 這種做法沒辦法使用之前提到的模板技術,后期維護難是一個重大問題。 數據多一點或者html復雜一點,手動拼接字符串耗費精力、容易出錯的弊端就會越來越顯現(xiàn)。 能不能先定義好模板,然后再做數據插入的操作呢?這樣就可以將模板定義和數據操作分離開來了,跟JS的字符串拼接Say good bye啦。 下面展示兩種分離數據操作和模板定義的實現(xiàn)方式: 如果要插入的數據剛好是在某個標簽或屬性內,可以使用操作DOM對象的方式來插入數據: 如果模板不是clone()得來的,要先用$(html)將HTML字符串轉成DOM對象,然后才能用find()去找到對應的DOM節(jié)點來操作哦。 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]); // 后面將詳細講這個函數的實現(xiàn)方式
}
$(".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節(jié)點并插入數據
dom.find(".tel").html(passenger.tel); // 找到存放乘客電話的DOM節(jié)點并插入數據
// 把處理完畢的DOM轉回HTML字符串并返回
return dom.prop("outerHTML");
}
注意點&細節(jié)解析