(转)【前端模板之路】一、重构的兄弟说:我才不想看你的代码!把HTML给我交出来!...
原文地址:http://www.cnblogs.com/chyingp/archive/2013/06/30/front-end-tmplate-start.html
寫(xiě)在前面
隨著前端領(lǐng)域的發(fā)展和社會(huì)化分工的需要,繼前端攻城濕之后,又一重要崗位橫空出世——重構(gòu)攻城濕!所謂的重構(gòu)攻城濕,他們的一大特點(diǎn)之一,就是精通CSS配置文件的編寫(xiě)。。。前端攻城濕跟重構(gòu)攻城濕是一對(duì)好基友,你寫(xiě)邏輯來(lái),我寫(xiě)樣式。
好吧,本文并不是介紹重構(gòu)攻城濕這個(gè)職業(yè)的,而是通過(guò)一個(gè)簡(jiǎn)單的場(chǎng)景來(lái)說(shuō)說(shuō):
1. 在用前端模板之前,我們是腫么動(dòng)態(tài)創(chuàng)建節(jié)點(diǎn)的
2. 為什么要使用前端模板
一個(gè)簡(jiǎn)單的場(chǎng)景
下面這張圖片看著應(yīng)該很眼熟吧?沒(méi)錯(cuò),是從mac QQ的好友列表里面截出來(lái)的。作為一名前端攻城濕,相信不少童鞋的第一反應(yīng)是:需要用什么樣的html結(jié)構(gòu)來(lái)標(biāo)識(shí)它?樣式要怎么寫(xiě)?
好吧,就假設(shè)我們可以用下面的dom結(jié)構(gòu)來(lái)標(biāo)識(shí)這個(gè)“好友”,不考慮其合理性,同時(shí),樣式部分我們?nèi)A麗麗地直接忽略
<div><img src="http://www.example.com/img/bg.png" /><h3>小卡的測(cè)試號(hào)</h3><div>大家好,我是個(gè)性簽名</div> </div>大家知道,我們的QQ好友列表是不固定的,于是必須得進(jìn)行“動(dòng)態(tài)創(chuàng)建”。我們通常會(huì)腫么做呢?
老濕說(shuō):createElement神馬的是王道
老濕曾經(jīng)諄諄教誨我們說(shuō),不要通過(guò)innerHTML來(lái)創(chuàng)建節(jié)點(diǎn),因?yàn)槟菚?huì)讓代碼變得混亂不堪。好歹也拿過(guò)優(yōu)秀少先隊(duì)員的稱號(hào),當(dāng)然得聽(tīng)老濕話了,于是我乖乖地寫(xiě)下如下代碼:
var card = document.createElement('div');var avatar = document.createElement('img'); // 頭像 avatar.src = 'http://www.example.com/img/header.png'; card.appendChild(avatar);var nick = document.createElement('h3'); // 昵稱 var nickTxt = document.createTextNode('小卡的測(cè)試號(hào)'); nick.appendChild(nickTxt); card.appendChild(nick);var signature = document.createElement('div'); // 個(gè)性簽名 var signatureTxt = document.createTextNode('大家好,我是個(gè)性簽名'); signature.appendChild(signatureTxt); card.appendChild(signature);createElement的問(wèn)題
筋疲力竭地敲完上面地代碼,我露出了滿足地微笑:老濕你坑我哪! 就這么幾個(gè)破節(jié)點(diǎn),讓我敲這么多代碼?
好吧,后來(lái)我才知道我錯(cuò)怪老濕了,他讓我用createElement地方式來(lái)創(chuàng)建節(jié)點(diǎn),但沒(méi)說(shuō)過(guò)讓我人肉敲啊。人類進(jìn)步的源動(dòng)力之一就是懶,計(jì)算機(jī)存在的很大價(jià)值就是為了解放生產(chǎn)力,干嘛不換個(gè)思路,讓代碼來(lái)幫我們生成代碼呢?代碼生成代碼?聽(tīng)著好玄乎,其實(shí)并不難,請(qǐng)看《【前端模板之路】二、人肉非智舉,讓代碼幫我們寫(xiě)代碼才是王道》
好吧,即使我們真的做到了“讓代碼為我們寫(xiě)代碼”,看看上面人肉敲的那坨東西,有沒(méi)有發(fā)現(xiàn)什么問(wèn)題?
自言自語(yǔ)神馬的最討論了,最大的問(wèn)題在于:dom結(jié)構(gòu)很不直觀,你壓根不知道你創(chuàng)建出來(lái)的節(jié)點(diǎn)結(jié)構(gòu)是神馬樣子的!!
換別人接手你的代碼,第一件事就是得把上面的代碼跑一遍,然后耐著性子打開(kāi)控制臺(tái)把dom結(jié)構(gòu)翻一遍,才能知道你上面那坨代碼究竟造了個(gè)什么鬼東西出來(lái)。好吧,那我改。。。
總結(jié)下:費(fèi)體力,不直觀
那些年,我們一起用過(guò)的innerHTML
毛少將說(shuō)過(guò):innerHTML是個(gè)好屬性!看看換做innerHTML我們會(huì)腫么做?
var card = document.createElement('div'); card.innerHTML = '<img src="http://www.example.com/img/bg.png" />' +'<h3>小卡的測(cè)試號(hào)</h3>' +'<div>大家好,我是個(gè)性簽名</div>';哇!只需要幾行代碼就搞定了,麻麻再也不用擔(dān)心我加班了!寫(xiě)代碼,so easy!
一切似乎很美好,但是,慢著!假如我們現(xiàn)在要?jiǎng)?chuàng)建一批節(jié)點(diǎn)呢?上面把資料都寫(xiě)死了不通用啊!
很簡(jiǎn)單嘛,把動(dòng)態(tài)變化的那幾個(gè)字段提取出來(lái)不就得了,如下代碼所示,瞬間高檔大氣上檔次
function createCard(avatarURL, nick, signature){var card = document.createElement('div');card.innerHTML = '<img src="'+ avatarURL +'" />' +'<h3>'+ nick +'</h3>' +'<div>'+ signature +'</div>'; return card; } createCard('http://www.example.com/img/bg.png', '小卡的測(cè)試號(hào)', '大家好,我是個(gè)性簽名');innerHTML的問(wèn)題
很好,字符串相加,一堆引號(hào),似乎看出點(diǎn)問(wèn)題來(lái)了。上面的場(chǎng)景算是很簡(jiǎn)單的,動(dòng)態(tài)變化的內(nèi)容不過(guò)就頭像、昵稱、個(gè)性簽名三個(gè),但現(xiàn)實(shí)世界遠(yuǎn)比我們預(yù)料的要復(fù)雜得多。如果我們想把顯示的好友資料再擴(kuò)展以下,加上在線狀態(tài)、是否會(huì)員、是否手機(jī)在線,那么,上面的代碼可能變成這樣(只是yy的)
function createCard(avatarURL, nick, signature, onlineState, isVIP, isMobileOnline){var onlineTxt = '';switch(onlineState){case 0:onlineTxt = '在線';break;case 1:onlineTxt = '離線';break;case 0:onlineTxt = '忙碌';break;default:case 0:onlineTxt = '在線';break;}var card = document.createElement('div'); // 有性能潔癖的兄弟看到下面的代碼表拿磚頭砸我card.innerHTML = '<img src="'+ avatarURL +'" />' + // 頭像'<h3>'+ nick +'</h3>' + // 昵稱'<div>'+ onlineTxt +'</div>' + // 在線狀態(tài)'<div>'+ (isVIP ? '會(huì)員' : '非會(huì)員') +'</div>'; // 是否會(huì)員if(isMobileOnline){card.innerHTML += '<div>'+ (isMobileOnline ? '手機(jī)在線' : '') +'</div>'; // 是否手機(jī)在線}card.innerHTML += '<div>'+ signature +'</div>'; // 個(gè)性簽名return card; }顯然,代碼開(kāi)始變得有點(diǎn)混亂了,再加上id、class以及其他屬性,相信我,絕對(duì)會(huì)很壯觀。。。
缺點(diǎn)總結(jié):可維護(hù)性較差(解決方案在后文會(huì)說(shuō)到)
重構(gòu)的童鞋說(shuō):我不想看你的代碼!
上面簡(jiǎn)單對(duì)比了createElement、innerHTML創(chuàng)建節(jié)點(diǎn)的兩種方式,細(xì)心的童鞋不難看出筆者的傾向性——innerHTML。
隨著前端領(lǐng)域的發(fā)展和社會(huì)化分工的需要,繼前端攻城濕之后,又一重要崗位橫空出世——重構(gòu)攻城濕!所謂的重構(gòu)攻城濕,他們的一大特點(diǎn)之一,就是精通CSS配置文件的編寫(xiě)。。。
前端攻城濕跟重構(gòu)攻城濕是一對(duì)好基友,你寫(xiě)邏輯來(lái),我寫(xiě)樣式。
>>重構(gòu)的兄弟說(shuō):把你的HTML交出來(lái)!
于是,我把之前的那段代碼給他,就是這貨
var card = document.createElement('div');card.innerHTML = '<img src="'+ avatarURL +'" />' +'<h3>'+ nick +'</h3>' +'<div>'+ signature +'</div>'; return card;>>重構(gòu)的兄弟:。。。誰(shuí)要看你的代碼,我要看HTML結(jié)構(gòu)!!
>>我:。。。要命有一條~~要不你把createCard 調(diào)用一下?
>>重構(gòu)的兄弟怒了:想試試千年殺?!!
>>我:??!!擦,別~~你騷等~~~
于是,我簡(jiǎn)單倒騰了一下,給了它下面這東西,還是最開(kāi)頭的那段HTML,只不過(guò)把所有動(dòng)態(tài)變化的內(nèi)容,用$XX的形式代替了
<div id="my_tmpl"><div><img src="${avatar}" /><h3>${nick}</h3><div>${signature}</div></div> </div>重構(gòu)的童鞋拿到他要的東西,心滿意足的就回去寫(xiě)他的CSS去了,那我們呢?也很簡(jiǎn)單,原來(lái)拼字符串,現(xiàn)在正則換變量,如下
var data = {avatar: 'http://www.example.com/img/bg.png',nick: '小卡的測(cè)試號(hào)',signature: '大家好,我是個(gè)性簽名' }; var html = document.getElementById('my_tmpl').innerHTML; html = html.replace(/\$\{(.+?)\}/g, function(all, $1){ // 將${XX}替換成data[XX]return data[$1]; });這里我們已經(jīng)隱約看到了前端模板的身影了,結(jié)構(gòu)、樣式與邏輯分離的第一步已經(jīng)實(shí)現(xiàn)了,重構(gòu)的童鞋根據(jù)約定好的HTML模板寫(xiě)CSS樣式,前端的童鞋負(fù)責(zé)往模板里填內(nèi)容、更新內(nèi)容,綁定事件,處理用戶交互等,這樣做的好處很明顯:
1. 結(jié)構(gòu)、表現(xiàn)、邏輯分離,便于重構(gòu)、前端童鞋的分工配合
2. 更好的可維護(hù)性,再也不用被一堆createElement,或破碎的字符串之間繞暈了
原來(lái)就是這貨:前端模板引擎的本質(zhì)
看著前面的${avatar}、${nick}等,很多童鞋應(yīng)該有似曾相似之感。沒(méi)錯(cuò),這里用的替換標(biāo)識(shí),跟jQuery Tmpl的變量替換標(biāo)識(shí)是一樣的,可參考https://github.com/BorisMoore/jquery-tmpl
前端模板引擎的本質(zhì),就是變量替換而已。
看到這里,你是不是覺(jué)得:原來(lái)這貨就是前端模板引擎啊,不過(guò)如此嘛!如果你有這種感覺(jué),那么:
1. 你以為前端模板引擎有多玄乎啊,本來(lái)繞來(lái)繞去,最終就是變量替換那么回事
2. Too young,to simple,sometimes, too naive. 前端模板引擎做的事情,除了變量替換之外,還要處理邏輯判斷、循環(huán)、模板嵌套、預(yù)渲染預(yù)處理等一堆東東,光有變量替換,實(shí)在不好意思說(shuō)是前端模板引擎。。
好了,之前還有個(gè)問(wèn)題等著解決,ctrl+f找到下面這段代碼
if(isMobileOnline){card.innerHTML += '<div>'+ (isMobileOnline ? '手機(jī)在線' : '') +'</div>'; // 是否手機(jī)在線}這其實(shí)就是邏輯判斷要做的事情,假設(shè)用的是jQuery Tmpl,下面這樣寫(xiě)就可以了
<div> {{if isMobileOnLine}}手機(jī)在線{{/if}} </div>jQuery Tmpl的用法,這里不打算展開(kāi),可參考:http://www.cnblogs.com/think8848/archive/2011/07/17/2108570.html
jQuery Tmpl的源碼剖析,請(qǐng)見(jiàn)后續(xù)文章~~
寫(xiě)在后面
本文通過(guò)一個(gè)場(chǎng)景的場(chǎng)景,引出我們?yōu)槭裁匆褂们岸四0?#xff0c;至于前端模板的設(shè)計(jì)這里暫時(shí)不提及,留待后續(xù)文章展開(kāi)。
想到哪寫(xiě)到哪,邏輯略凌亂,包涵~碼字不易,請(qǐng)隨手點(diǎn)推薦~~
轉(zhuǎn)載于:https://www.cnblogs.com/fcsh820/p/3175047.html
總結(jié)
以上是生活随笔為你收集整理的(转)【前端模板之路】一、重构的兄弟说:我才不想看你的代码!把HTML给我交出来!...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 替换字符串中指定的字符--随手源码
- 下一篇: VS让人纠结的Release和网站一键发