一直想總結下本身摸打滾爬的前端經歷,3年,從一個極討厭前端的人,變成一個吃前端飯碗的人。沒有人帶過我,跌跌撞撞的緩慢前進,但我很喜歡分享,喜歡一塊兒進步,這會是我之後一直樂意作的事情。javascript
w3cschool上的 html / css / javascript / 以及jquery教程,萬事開頭的第一步css
Say hello to the world!html
jquery 輕鬆玩耍DOM和event前端
jquery-ui 加強的UI組件java
Bootstrap 今後傻瓜式排版就能搞定jquery
Bootstrap 主題模板 and 管理系統模板 快速搭建項目,簡單,好看git
在小跑上路的過程當中,作出來的東西看起來很專業,注意是「看起來」。若是不理解真正的前端技能,那隻能是看起來專業,內部結構仍是亂糟糟的,或者是遇到bug不知道怎麼調,東一句西一句,拆了東牆補西牆。這過程就像走在平衡木上,稍不留神就會摔下去。github
關於js的原型和做用域,我沒專門寫過文章,建議去博客園搜下。若是想要完整的理解js語言機制,能夠去看《Javascript模式》這本書,或者看我整理的讀書筆記
只有把平衡木上的技能磨熟練後,咱們才能真正的遊刃有餘,保證不從平衡木上摔下來的前提下,再有餘力去設計如何華麗的跳躍和謝幕。
還沒了解js對類(或模塊)的封裝前,咱們的代碼多是這樣的
var getData = function(){ // ...... }; function editFunc(){ // ...... }; $('.refresh-btn').on('click', function(){ var data = getData(); var $target = $($(this).attr('data-target')); $target.empty(); for(var i=0; i<data.length; i++){ var $child = $('<tr></tr>'); $child.append('<td>' + data[i]['name'] + '</td>'); // ...... $child.append('<td><a class="edit-link">編輯</a></td>'); $target.append($child); } $target.find('.edit-link').on('click', editFunc); });
一個點擊就獲取數據,而後刷新表格的功能。若是一個頁面中有多個相似的異步刷新的表格,且每一個表格的字段又各不相同,那麼最偷懶的作法就是拷貝大段代碼,而後再調整<td>
的字段。這樣的代碼簡直了,太難維護了!
var table1 = new AjaxTable({ el: '#dataTable', dataUrl: '/path/to/action/' }); table1.refresh();
若是代碼變成這樣,那就爽多了,獲取數據和刷新表格的過程都封在了AjaxTable
中,各個使用之處只須要傳個參數調用下refresh()
便可,減小了大量重複(類似的)代碼。這就是對UI組件/功能組件的封裝。
之前爲了準備面試時的「手撕代碼」,寫過一個簡單的輪播組件,不用jquery(面試常常不容許使用任何庫)
還寫過下面一些文章
爲Highcharts作包裝 (有點相似上面示例中的AjaxTable
)
一步步作組件-學校選擇器(系列) (系列長文,如何把一段生硬實現的代碼一步一步封裝和擴展成爲一個可配置的UI組件)
若是要在頁面上引入外部的js庫,最初學習的時候是這樣引入的
<script type="text/javascript" src="jquery-1.7.2.min.js"></script> <script type="text/javascript" src="jquery-ui/jquery-ui-1.8.24.min.js"></script> <script type="text/javascript" src="jquery-ui/jquery-ui-datepicker-zh-CN.js"></script> <script type="text/javascript" src="bootstrap-2.3.2.min.js"></script>
因爲瀏覽器中js的執行(非加載)過程是在單線程中的,而各js文件又會存在依賴關係,好比 jquery-ui 依賴 jquery,bootstrap 也依賴 jquery,因此<script>
標籤的引入得知足依賴順序。當一個項目越作頁面越多時,這麼多頁面中會存在一堆<script>
標籤,若是要將某個js文件升級版本,或者修改script的依賴關係時,這就會成爲一個很繁瑣的工做,特別是<script>
分散在項目的各個文件中時。
RequireJS就是出來解決這個問題的(簡單來講就是用js去管理js),還有SeaJS,它們分別表明着AMD和CMD兩種風格,關於模塊化和二者的區別能夠看這篇文章。
頁面繼承 這塊跟上面的各類具體的技術沒太大關係,頁面繼承主要是用來組織項目文件結構(或頁面結構)的一些經驗規則。假設在一個系統裏,每一個頁面都有相同的頭和尾,還有nav,那根據上面封裝和分離的思想,咱們可能會這樣寫
<html> <body> %{ include header.html }% <div class="container"> <div class="left"> %{ include nav.html }% </div> <div class="main"> <!-- 具體業務... --> </div> </div> %{ include footer.html }% <script src="require.min.js"></script> <script type="text/javascript"> requirejs.config({ // 全局配置... }); </script> <script type="text/javascript"> require(['jquery'], function($){ // 具體業務... }); </script> </body> </html>
咱們能夠把這一段做爲一個base的父頁面,命名爲base.html
,每一個「具體業務」的頁面都繼承自它。
%{ extends 'base.html' }% %{ block styles }% <style type="text/css"> </style> %{ endblock }% %{ block content }% <div>具體業務...</div> %{ endblock }% %{ block scripts }% <script type="text/javascript" require(['jquery'], function($){ // 具體業務... }); </script> %{ endblock }%
把這個頁面叫作func1.html
,具體業務的頁面中只會包含自身業務功能須要關心(用到)的東西,不去多管base頁面的閒事。能夠看到子頁面中有不少block
之類的錨點,會將與endblock
之間的內容插入到父頁面中的相應位置,因此要先在base.html
中「挖好坑」。
%{ block styles }% %{ endblock }% %{ block content }% %{ endblock }% %{ block scripts }% %{ endblock }%
具體作法能夠去看常見的模板系統,本例中參考的是Django中的模板定義。
頁面組件化 也是和具體技術沒有關係,它是順着 頁面繼承 的思路,把頁面或文件結構作更小粒度的拆分,頁面由一個個頁面組件構成。
%{ include sectionA.css }% %{ include sectionB.css }% <div class="row"> %{ include sectionA.tpl }% </div> <div class="row"> %{ include sectionB.tpl }% </div> <script type="text/javascript"> require(['sectionA', 'sectionB'], function(A, B){ var App = Base.extend({ _init: function(){ var that = this; var mods = [A, B]; this.modules = []; mods.forEach(function(Module){ that.modules.push(new Module(App)); }); } }); }); </script>
上面至關於一個業務頁面,它由sectionA
和sectionB
兩個頁面組件組成,sectionA.tpl
和sectionB.tpl
是html模板。在應用層(即業務)頁面中初始化兩個js模塊A
和B
,而且把自身的App
變量傳遞給模塊(new Module(App)
),能夠實現子模塊與應用層頁面的通訊,甚至是模塊之間的通訊。
這樣把頁面拆成粒度更細的結構,好處是頁面模塊能夠複用,也便於管理,改動頁面中的一小塊時只需在所處的模塊中,縮小改動的影響範圍。
還看過一種思想是,把css文件也當作資源由requireJS動態加載,這樣上面示例中的include xxx.css
都不須要了,頁面模塊的css資源做爲該模塊的依賴,寫在js模塊的define
的依賴中。
define(['jquery', 'sectionA.css'], function($){ // 業務模塊... });
這樣把css和js都抽象成「資源」,至關於
組件 = 模板 + 資源
一個頁面總體的模板,至關於多個頁面組件的拼裝而成。更進一步,若是能讓頁面組件作到異步渲染的話(便可以由js去解析模板語法和變量,而不是交給web框架),才能真正作到頁面渲染的本質:
呈現給用戶的頁面 = 頁面模板 (包括組件的模板) + 數據
「渲染」就是將帶數據變量的頁面模板輸出成標準的html,同步渲染是指在服務端解析模板並輸出完整html到瀏覽器中,而異步渲染指直接在瀏覽器中經過javascript 根據傳入的數據將模板輸出成標準html。
同一模板若是既能在服務端同步渲染,又能在瀏覽器端異步渲染的話,咱們就不須要關心「數據」是後端框架直接輸出到頁面的,仍是ajax動態取來的。對模板來講,數據就是個「接口」,而 模板 + 數據 = 渲染
。這樣咱們做爲前端,才能把更多精力放在模板和交互上,不用管數據的傳遞方式。
前端發展了十幾年,如今幾乎到達頂峯的速度了,近兩年推出的框架層出不窮,jquery早已不是一統江湖了。每一個人的精力都有限,不可能一個個都學過來,可是必須認可,前端是一個完整的體系(我以前整理的知識體系),有它獨特和魅力之處。不只是框架,還有更多的工程化問題,框架都是爲了解決某類相通的問題而生。模板和數據分離也好,「狀態」和「表現」分離也好,我愈來愈體會到
「分」是爲了「合」
這條平凡之路,還會「頻繁」的發展和融合下去。
本文最先發表在個人我的博客上,轉載請保留出處 http://jsorz.cn/blog/2015/12/twisted-way-to-awesome-fe.html