好久好久之前……………………的好久好久的之後,也就是昨天的昨天(2012-07-07),D2前端技術論壇,下午3點,分會場,@老趙分享其開源項目(什麼來着?名字彷佛很難記,讓我找找~~)Jscex. 印象較深的是末了,其戲稱seajs爲高富帥。javascript
爲什麼有此感慨?一樣是開源項目,seajs由於①原做者我的影響力②推廣渠道或者說團隊影響力③背後乾爹的大力支持等緣由,其知名度以及接受程度要比Jscex高很多。css
我本身彷佛也有相似的感觸,10年年初的時候,我本身折騰了一個關於CSS3的小項目,有別於通常的參考文檔,這裏容許用戶(主要是同行)添加相關的文章,以及一些須要注意的技術點。
html
雖知響應應甚少,然而,幾年下來,令我嘖舌的是,竟然沒有1條更新信息時出自他人之手。頭一年,我還樂此不疲地更新相關文章以及本身發現的一些知識注意點,但後來,本身也繳械投降,懶得折騰了,純碎看成靜態的參考文檔看了。前端
所謂獨木難支,我的的精力老是有限的,影響力也是有限的。不少時候,本身折騰點東西就像鵝毛飄到水裏同樣,漣漪都沒一個,不免心有悸動:要不去傍個高富帥、白富美~~java
哈哈,不過人貴自知,不是人人都能成爲郭美美的,沉澱心態,低調蛻變,說不定,之前一些渴求的東西會以附加產物的形式悄悄來到你的身邊。node
我記得大學,應該是根叔吧,關於畢業,其說過(大體意思):「若是畢業的時候,你以爲你作什麼都沒有問題,那你就是合格的本科生。」
我將其理解爲:畢業真正考量的不是學到了多少東西,而是是否有足夠強大的學習能力。css3
很多人詢問過我,CSS該怎麼學,JS該怎麼學?我能回答的可能是,要重視基礎,要捨得吃苦~~至於其餘的,說得再多,其實也不必定有用。一來每一個人的學習能力與領悟力有差別;二來,本身的學習方法不必定適合他人。指個大方向,應該更有用的,正所謂「師父領進門修行在我的」。git
基礎是個很玄妙的東西,紮實的基礎猶如武俠裏男主角深厚的內功,內功深厚了學什麼其餘功夫都很快,並且能夠很好駕馭;一樣,基礎紮實,一些新技術什麼的上手也快,並且能夠自如靈活運用!程序員
前端發展突飛猛進,熱門的東西容易產生很強烈的熱氣,令人產生浮躁之氣,尤爲對於新手而言,這種燥氣是不利的。說不定就會捨本逐末,我忽然想起了@漁人碼頭以前發過的一個微博——「說實話看了這標題,看了這年齡,看了這評價,我鴨梨山大!鴨梨山大!鴨梨山大!」,圖以下:
github
所謂「資深」,並非順應所謂的潮流,追逐一些新東西。這些光鮮亮麗,華而不實的東西,猶如時尚的衣服同樣,第二年就老氣過期了。潮流一直在前行,而你,卻停不了;由於一旦停下來,就落後了,out了,這樣的過活是很累的;而實際上,你所掌握的又可能都是些浮於表面的東西,不過卻是糊弄糊弄些外行,混口飯吃吃!
貌似扯遠了,趕快,用繩子拴住,拉直,用力拉,拉啊,拉……尼瑪,終於拉回來了,擦下汗,咱們回到正題,關於seajs. seajs能夠算是前端屆國產新貴,其年齡(我不肯定)應該小於2歲,不過百度之,能夠看到相關的文章仍是很多的,確實有「高富帥」的跡象。seajs主要處理模塊加載,基於commonjs規範,使用spm壓縮合並顆粒JS模塊。
具體如何如何使用,如用法啊,參數啊什麼的,能夠點擊這裏的手冊進行查看。更深刻的理解能夠參考原做者@玉伯也叫射鵰在D2上分享的PDF文件(來自微盤)。
下面這篇文章也是很不錯的:JavaScript模塊化開發庫之SeaJS,對模塊等對比的分析解釋是很受用的。
下面我想講講我是如何學習相似seajs這樣的新東西。
新東西的學習
1.感性認識,情感化認知
並非全部的程序員都適合作前端,聽說,只有20%~30%, 緣由?我想,可能一部分緣由就是情感化思惟,畢竟,咱們所作的東西離用戶是很接近的。就我而言,我很在乎一個新事物從總體上給個人feeling, 這種感性的認識可讓我準確的把握這個事物的特質,因而會造成更合適的策略處理之。換個容易理解的說法:關於追求新認識的姑娘,我很在乎這個姑娘總體上給個人feeling, 這種感性的認識可讓我準確把握這個姑娘的特質,因而,腦中會天然造成更合適的追求策略。微博上不是有這麼個段子嘛:追女孩子,若是這個女孩懵懂無知,就帶她去看世間繁華;若是這個女孩看盡世間百態,就帶她去騎旋轉木馬!總體感受(感性認識)→類型特質→追求策略。
如今的問題是,若是得到準確的總體feeling呢!道聽途說,一面之緣等容易產生誤差。咱們須要經過多個途徑去了解。首當其衝是官方網站對其描述;而後,就是其餘人對其評價,認識等。仍是追妹子例子,去官網至關因而詢問其父母對這個姑娘的評價(固然,父母都會慣着本身的孩子,很差的話通常都不會說的);詢問其餘人就是詢問姑娘朋友們、同事們的評價,非誠勿擾不少男嘉賓就死在「好友評價」環節,可見後者仍是相對比較客觀的!
所以,反應到現實就是,去官方網站查看,若是是開源項目,也能夠去github查看;查看同行們寫的相關文章或微博,看看其餘人是如何介紹與評價的。
2. 實現方式、API參數
就像咱們使用一個全新的jQuery插件同樣,其中必經一步是查看文檔,熟悉其API,知道其一些特殊用法等。 比如要熟悉姑娘身高體重,三圍,鞋子尺碼,知道姑娘的一些癖好等。
3. 實踐出真知
古語有云:紙上得來終覺淺,絕知此事要躬行。實踐是必須的。爲什麼?
首先,不少時候,咱們面對一個全新的東西,其文檔或手冊上API用法、解釋等會讓咱們不知所云,disorder – 混亂。彷彿回到了大學學「拉普拉斯不等式」的時候,看得頭疼。可是,若是你經過本身製做實例,一個一個嘗試其所說的內容,不少一眼看上去頭疼的東西,立馬變得猶如春風拂面。
其次,由於是全新的東西,人總不免被過往的經驗(或者說慣性思惟)束縛,有些內容真正意思可能並非腦中所想的那樣。舉個例子,按照經驗式的理解,console.log([2, 10].sort())
的結果應該是[2, 10]
,然而,實際上,在JavaScript中,結果是[10, 2]
, 字符串排序。這種跟以往經驗不一樣的表現差別須要經過實踐纔能有切身的體會。
這也是爲什麼會出現「婚前試愛」這種現象的緣由。
seajs的實踐
您可能跟我同樣,也是最近才接觸seajs, 您可能也跟我同樣,被手冊上頻繁出現的dependencies, factory等詞閃花了眼睛。只怪爾等JavaScript不夠精深,可是,seajs號稱API簡單,所以,雖然一些深刻的東西咱們一會兒消化不了,可是,這並不影響咱們使用這個工具。
如何使用?很簡單,既然seajs是用來模塊化JS的,所以,咱們想一個稍微複雜,又能承受的例子做爲實踐,從頭至尾走一遍,順便spm也摸索下,若是都經過,天然……你說姑娘都讓你實踐了,從頭至尾都*(和諧)過了,順便*(和諧)也摸索過了。好了,你們都懂的……
OK, 我想了想,就實現一個簡單的彈出框效果,有必定數量的模塊JS, 功能實用,且不復雜。下面,若是你是新人,能夠跟我一塊兒,看看,如何使用seajs模塊化相關腳本,同時實現的彈出框效果。
如下實現爲本身的思路,可能比較低級與囉嗦,熟悉seajs的人能夠直接跳過。
1. 半透明背景遮罩層
說到彈框,首先想到的是後面黑色半透明的遮罩層。咱們就套用:
define(function(require, exports, module) { // 模塊代碼 });
這種寫法應該就能夠了,須要暴露的接口直接exports.*
就能夠了。
恩,咱們新建一個名叫overlay.js
的JavaScript文件;而後,咱們就着手建立這個遮罩層元素。Wait! 這個建立元素的方法應該模塊化,方便其餘地方公用,例如彈框中元素建立等。
所以,咱們須要把overlay.js
擱置一邊~~
2. 元素建立模塊JS
同目錄下,新建一個名爲elementCreate.js
的JavaScript文件,一樣的套用,以下JavaScript代碼,註釋也要規範哦~~
/** * 建立元素 */ define(function(require, exports) { exports.create = function(tagName, attr) { var element = null; if (typeof tagName === "string") { element = document.createElement(tagName); if (typeof attr === "object") { var keyAttr, keyStyle; for (keyAttr in attr) { if (keyAttr === "styles" && typeof attr[keyAttr] === "object") { // 樣式們 for (keyStyle in attr[keyAttr]) { element.style[keyStyle] = attr[keyAttr][keyStyle]; if (keyStyle === "opacity" && window.innerWidth + "" == "undefined") { element.style.filter = "alpha(opacity="+ (attr[keyAttr][keyStyle] * 100) +")"; } } } else { if (keyAttr === "class") { keyAttr = "className"; } element[keyAttr] =attr[keyAttr]attr["class"]; } } } } return element; }; });
exports.create
表示模塊暴露在外的方法名稱是create
, return element;
表示該方法返回的是建立的元素對象。
3. 回到半透明遮罩層
如今,咱們就可使用elementCreate.js
模塊了,要使用這個模塊,就得使用require
這個函數(注意:require
名字必須是require
,不能修改)。
var elementCreate = require("./elementCreate");
因而,var element = elementCreate.create("div", {});
就能夠建立一個div元素啦!相關完整代碼以下(具體遮罩層實現細節能夠忽略):
/** * 黑色半透明遮罩層 */ define(function(require, exports, module) { var elementCreate = require("./elementCreate"); var overlay = (function() { var element = elementCreate.create("div", { styles: { display: "none", width: "100%", backgroundColor: "#000", opacity: 0.35, position: "absolute", zIndex: 1, left: 0, top: 0, bottom: 0 } }); document.body.appendChild(element); return { display: false, show: function() { element.style.display = "block"; this.display = true; return this; }, hide: function() { element.style.display = "none"; this.display = false; return this; } }; })(); exports.overlay = overlay; });
您能夠狠狠地點擊這裏:seajs下黑色半透明遮罩效果測試demo
demo頁面實際上已經演示了seajs的應用,代碼以下:
<script src="sea.js"></script> <script> seajs.use("./overlay", function(overlay) { // overlay.overlay就是遮罩層元素相關對象 }); </script>
4. 彈框了
遮罩層搞定了,下面就是彈框了。咱們新建一個名爲」flbox.js
「的js文件。實現彈框效果,首先要黑色半透明層(能夠require
overlay.js
模塊),而後標題欄,關閉按鈕等建立(能夠require
elementCreate.js
);最後,彈框裏面內容須要Ajax加載,可是,並無ajax的模塊,所以,咱們要讓ajax模塊插下隊,先搞定之。
5. ajax模塊
由於是示例頁面,所以,咱們沒有必要寫得很完善與詳細,這裏,咱們就能夠單純實現使用get
方法加載外部一段HTML。因而,搗鼓搗鼓,以下代碼:
/** * ajax方法 */ define(function(require, exports) { exports.get = function(url, succCall) { if (url + "" === "undefined") { console.log("請求地址缺失!"); return; } var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200 && typeof succCall === "function") { succCall.call(xhr, xhr.responseText); } }; xhr.open("GET", url, true); xhr.send(); }; });
輕輕鬆鬆,您能夠狠狠地點擊這裏:ajax模塊測試demo
測試OK,如今回到彈框模塊。
6. 彈框模塊
下面,須要的模塊都有了,咱們只要require
進來,就能夠用啦!
require("./elementCreate") require("./ajax") require("./overlay")
雖然,單純地展現代碼我本身也以爲挺傻的沒勁,可是,對於天地不知的初學者而已,這種餵奶喂到嘴邊的方式是他們學習所須要的。
/** * 簡易彈框 */ define(function(require, exports) { var funCreate = require("./elementCreate") , funAjax = require("./ajax") , overlay = require("./overlay"); var eleWin = funCreate.create("div", { styles: { display: "none", position: "fixed", left: "50%", zIndex: 2 } }) , eleBar = funCreate.create("div", { styles: { fontSize: "12px", padding: "8px", backgroundColor: "#eee" } }) , eleClose = funCreate.create("a", { href: "javascript:", styles: { fontSize: "12px", color: "#34538b", textDecoration: "none", position: "absolute", margin: "-22px 0 0 85%" } }) , eleBody = funCreate.create("div", { styles: { backgroundColor: "#fff", borderTop: "1px solid #ddd" } }) , eleOverlay = overlay.overlay; eleWin.appendChild(eleBar); eleWin.appendChild(eleClose); eleWin.appendChild(eleBody); document.body.appendChild(eleWin); eleBar.innerHTML = "彈出框"; eleClose.innerHTML = "[關閉]"; eleClose.onclick = function() { flbox.close(); return false; }; var flbox = { loading: function() { eleBody.innerHTML = '<div style="width:200px;height:100px;padding:10px;">加載中...</div>'; this.position(); }, open: function(url) { var self = flbox; funAjax.get(url, function(html) { eleBody.innerHTML = html; self.position(); }); }, position: function() { eleWin.style.display = "block"; eleOverlay.show(); var widthWin = eleWin.clientWidth , heightWin = eleWin.clientHeight; // 定位 eleWin.style.marginLeft = "-" + widthWin / 2 + "px"; eleWin.style.top = (screen.availHeight - heightWin - 100) / 2 + "px"; }, close: function() { eleOverlay.hide(); eleWin.style.display = "none"; eleBody.innerHTML = ""; } } exports.open = flbox.open; });
7. ajax地址增長隨機數
爲了不彈框打開時IE瀏覽器下的緩存問題,咱們須要一個url地址增長隨機查詢字符串的方法。新建名爲queryRandom.js
的模塊JS文件,鍵入以下代碼:
/** * URL地址後面增長隨機參數 */ define(function(require, exports, module) { exports.queryRandom = function(url) { var strQueryRandom = "random=" + Math.random(); var arrQuery = url.split("?"); if (arrQuery[1] != undefined) { // 含查詢字符串 if (url.slice(-1) === "&") { url = url + strQueryRandom; } else { url = url + "&" + strQueryRandom; } } else { // 不含查詢字符串 url = url + "?" + strQueryRandom; } return url; }; });
您能夠狠狠地點擊這裏:seajs增長隨機查詢demo
8. 萬事具有、終極測試
如今,咱們新建一個主線js, 命名爲main.js
, 配合demo頁面,咱們寫個很簡單的方法——即點擊某連接,彈框顯示該連接href屬性所對應的頁面內容。
完整代碼以下:
/** * 主線js * 點擊小圖查看大圖測試 */ define(function(require, exports) { var query = require("./queryRandom") , flbox = require("./flbox"); exports.bind = function(element) { element.onclick = function() { var href = this.href; flbox.open(query.queryRandom(href)); return false; }; }; });
您能夠狠狠地點擊這裏:seajs實現簡易彈框效果demo(不支持IE6瀏覽器)
而調用的腳本很簡單:
seajs.use("./main.js", function(test) { test.bind(document.getElementById("test")); });
這很好地體現的seajs API簡單的優勢。
因而乎,遵循commonjs寫法規範的各個子模塊們,在seajs簡單的API下,組合出了咱們想要的彈出框效果。而,這些子模塊們,又能夠被用在其餘地方。沒有腳本衝突,沒有上線時差衝突。可維護性大大提高。這就是seajs的意義所在。
上面簡易彈框效果相關代碼我已經打包了,點擊這裏(右鍵 – [目標|連接]另存爲):seajs-flbox.zip
雖說,咱們須要的彈框效果已經實現了,可是,倒是不能直接上線使用的,爲什麼?
咱們看下其http請求,以下截圖:
哎呀呀,這麼多JS請求,嚇着烏索普脆弱的當心臟了。雖然,seajs模塊化的書寫提升了維護性,可是,也帶來了前端性能的問題!如何解決?
如今,就是救世主spm出場的時候了,spm → seajs package manage?
spm能夠合併並壓縮seajs中的各個模塊JS文件。仍是上面的彈框demo頁面,咱們在地址後面增長」?spm=1
「,以下圖所示,訪問之:
再次刷新頁面,查看HTTP請求數,額哈哈,本來6個JS請求,如今合併成1個啦:
命令行中以下代碼即實現效果:
spm build main.js --combine --app_url zxx
而後,main.js中所用到的相對路徑require的全部模塊就會合並並壓縮,新生成的文件(若是沒有指定輸出路徑)會是__build/main.js
spm的安裝與使用
spm安裝與使用github上有介紹。大體以下:
安裝
先安裝node和npm, http://nodejs.org/#download;而後安裝spm, 以下命令行代碼:
$ npm install spm -g
build[option]模塊
壓縮一個JS模塊:
$ spm build a.js
壓縮併合並:
$ spm build a.js --combine
壓縮併合並全部獨立模塊(包括絕對路徑的):
$ spm build a.js --combine_all
清除建立的文件:
$ spm build --clear
經過定義build-config.js
能夠作更多的事情:
build-config.js:
module.exports = { "base_path": "/path/to/libs/", "app_url": "http://test.com/js/app/", "app_path": "/path/to/app/", "loader_config": "path/to/init.js" };
更多信息,能夠調用:
$ spm help build
以上爲我以爲經常使用的。這裏推薦一篇關於smp使用的文章:seajs的spm使用摸索。這篇文章對spm各個參數都有解釋,另外,還提供了自定義輸出路徑等參數的使用示例。能夠說是對github上使用的很好補充。
smp我也是新手,也沒有什麼其餘心得什麼的,就這樣吧~~
中小的企業有其自己的侷限性,例如優秀的技術人才,有事就會產生一些無奈。切身說法,咱們的web端相關的JS腳本中各個模塊從誕生之初就在一個JS文件中,住在一間房子裏。通常狀況下是沒有問題的,可是,多多少少會出現這樣的情況:
項目經理:我們這個圖片上傳模塊要改下,後天上線!
前端仔:沒問題。由於前端仔成功約到了和女神一塊兒看電影,一來興奮;二來怕加班。其進入仙人模式,歘歘歘三下五除二把JS端的改動都搞定了,就等後臺那邊對頁面修改了!
可是,剛改完不久,悲劇來了——項目經理:趕快,發現一個重大bug, 支付計算貌似有漏洞,趕快fix它,上線!
前端仔:沒問題。又進入無敵模式,快刀斬亂麻,漏洞補上了。結果,準備發佈JS上線的時候,前端仔抓狂了
尼瑪,不能上啊。圖片上傳頁面還沒改,上線了雖然支付沒有問題,可是,圖片上傳被搞殘了啊!
因而本來興奮的前端仔像被艾尼路劈了同樣,焉了。因而,回到苦逼狀態,把以前改好的圖片上傳模塊又改回先前的樣子……
這就是沒有模塊化的痛苦。然而,問題早就知道,可是,一直沒有去解決,爲什麼?沒人搞這件事。其實,靜態資源壓縮併合並對於有經驗編程人員講並非難事。看大衆點評網,雖然你們都是使用MooTools, 可是,其靜態資源就能夠壓縮合並,可是,咱們這裏,沒人弄,雖然提過,雖然有人說過願意作這個事情。我曾研究過淘寶開源的一個JS合併加載工具,可是是PHP的,而咱們用的.net
, 有點折騰不來!因而,就這樣拖着~~
不過,如今,貌似能夠不用依賴.net
程序員們了,在node環境下,使用seajs模塊化書寫,spm合併並壓縮。先前的一些維護問題顯然不復存在。因而,咱們的精力能夠更多地放在代碼實現以及如何更好地劃分模塊上,這有助於工做效率的提高。
所以,seajs我是會去使用的,雖然它的做者不是foreigner. 至於文章一開始提到的Jscex, 恩……它能夠幫我把到妹子嗎?不能!能夠幫我釣到大魚嗎?不能!能夠幫我車子加油嗎?不能!所以,我感受我不會去用它。
扯淡居多,但願不會浪費您寶貴的時間。感謝閱讀,若是表述不許確之處,歡迎指正。
對了,我有問題求教:在彈出框實例頁面中,(require, exports, module)
這三個參數惟獨module
一次也沒有使用,所以,我想問下,module
在何種情境下使用,有何做用?
原創文章,轉載請註明來自張鑫旭-鑫空間-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=2476