seajs學習一天後的總結概括

  公司項目最近須要將js文件遷移到seajs來進行模塊化管理,因爲我之前主要接觸模塊化開發是接觸的AMD規範的requireJS,沒有接觸過CMD規範,並且在實際項目中尚未用過相似技術。因而,我很是興奮的開始了seajs的學習,正好對模塊化開發仰慕已久,終於有機會大展身手了!jquery

  一開始老是有點曲折的,我照着玉伯的github上的教程一步步來,而後發如今我引入jquery的時候,require到的jquery居然是undefined,通過一番摸索,我發現原來jquery是基於amd規範的,seajs官網的例子之因此可以成功引入jquery,是由於其jquery是採用cmd規範模塊化以後的產物,而顯然我從百度cdn上拿下來的jquery是沒有通過該處理的。百度了一下,發現jquery想改形成seajs能引入的模塊,有至少兩種方法ios

 

  1.在jquery源碼外層套上define,將其以cmd的規範模塊化git

  2.找到jquery最後幾行的&&amd的條件,可使用ctrl+f搜索amd便可找到,刪掉該條件github

 

  顯然,第二種方法更爲方便,改造以後,果真jquery可以正確引入了,不過據其餘部門同事的反饋,改造後的jquery模塊在某些狀況下會出現莫名其妙的bug,據他說在ios上有bug,因爲暫時沒遇到bug,所以暫且仍是先將jquery也封裝爲模塊數組

  seajs的基本配置仍是比較簡單的,首先,在最前面先引入seajs自己,這應該是毋庸置疑的,而後開始配置seajs,這裏我遇到一個坑,網上部分教程指出config可使用data-config來引入,寫在單獨文件裏,我愉快的這樣作了,而後一直報錯,發現路徑指向錯誤,糾結了我半天,最後忽然看到原來不知道從哪一個新版本開始移除了這個屬性,個人天,太逗了less

廢話少說,正式開始配置異步

1 seajs.config({
2    base:"../sea-modules",
3    alias:{
4         "jquery":"jquery/jquery.min.js"
5    }
6 });

如下便是seajs經常使用屬性的用法:async

base提供基礎路徑模塊化

alias是別名,用於將較長的路徑簡化 以上兩個參數是最基本的參數,實際上還有如下幾個參數函數

paths:用來統一路徑前綴,適用於較長的外網前綴

preload:預加載部分模塊,貌似已移除

debug:設置爲true開啓調試模式,在控制檯輸出一些錯誤警告

map:將某個路徑映射到另外一個,經常使用於在線調試,好比spm構建獲得的通常有xx.js和xx-debug.js,此時可用map將.js映射爲-debug.js,方便在線調試

vars:設置seajs自帶變量,可用{變量名}來獲取,經常使用於模塊路徑一開始不肯定的狀況,例如中文或英文,zh-cn或en,該變量是加在路徑上的,src="../{變量名}/main.js"

charset:引用script文件時的charset屬性,默認爲utf-8,該屬性能夠爲函數,具體值爲函數返回的值

另外seajs.config函數能夠運行屢次,屢次運行會自動合併配置的參數 配置結束後,開始寫入口函數

seajs.use("../static/main"); 

 

這是最基本的入口,use方法用來引入模塊,此處我引入了main.js,也就是入口js 因爲seajs是異步加載模塊的,因此這裏還能夠加入回調函數,傳入一個形參,便可獲取到main模塊,接下來就能夠調用main暴露出來的方法 配置完,寫完入口,接下來就是重頭戲,寫模塊了 seajs遵循cmd規範,要求每一個模塊須要按該規範風格書寫 即

define(id,dependencies,function(require,exports,module){
   //前面兩個參數,一個是當前模塊惟一標誌,一個是當前模塊依賴的模塊。正常狀況下沒必要指定這兩個參數,seajs會幫咱們自動獲取,第三個factory函數是模塊的工廠函數
   //require用於獲取其餘模塊,如:
   var a = require("moduleA");  //此處require內寫的名稱能夠是具體路徑,也能夠是alias裏定義的別名,通常寫的是別名  
   //經過require語句執行了對應的模塊函數,並返回該模塊的module.exports對象
   //注意,除了返回對象外,也執行了該函數,好比,該模塊裏若是有一句alert(1)不在exports暴露的方法裏,會在require調用的同時直接執行。
   a.fn();//獲取到a模塊後,便可調用a模塊暴露出來的方法
})

如下是a模塊,一樣使用cmd規範

define(function(require,exports,module){
  var bb="no bb";
  exports.fn=function(){
  console.log(bb);
};
});

顯然,用腳也能想到控制檯會打印 「no bb」,  cmd規範裏比較重要的概念就是使用exports來暴露屬性或方法, 例如exports.a=3,exports.fnn=function(){}, 這樣其餘模塊用require關鍵字獲取到對象的同時,就能使用這些暴露出來的屬性或方法了。

可能有人已經注意到了,咱們的factory函數裏三個參數,前面兩個已經用到了,require用來獲取模塊,exports用來暴露模塊,那第三個參數呢,有什麼做用?

問得好!其實一開始我也很納悶,這個玩意究竟是幹嗎的,通過一番研究,我大致上瞭解了這個參數 ,原來require獲取到的模塊實際上最後返回的是module,而調用方法也是經過module.exports獲取到的 exports是module.exports的一個引用,至於爲何要拐個彎,我我的猜想有兩個緣由(做爲一個初學者大膽的猜想,若是有誤歡迎指正)

1.名字短,寫的爽。好吧,我開個玩笑。

2.避免隨意改動模塊對象,這個纔是重點,前面也強調了exports只是一個引用,其指向了module.exports的內存地址 可是引用畢竟是引用,修改引用是不會改動被引用的對象的。

舉個例子說明一下。

module.exports=5;

exports=3;

此時require後返回的值就會是5,而不會是3,這就是引用和自己最大的區別。

關於這兩個的區別有一個新手使用常犯的錯誤。好吧,我沒犯過(得意中~) 某些場景裏,咱們頻繁使用exports向外提供接口,可能寫了多個exports.xxx=xxx 。

這個時候,初學者可能會想我能夠這樣寫

exports={ 
  a:xxx,
  b:xxx,
  c:xxx
}

想一想就激動啊,這樣寫多專業,就好像js面向對象裏,給構造函數的prototype拓展方法和屬性時,也會用到這種寫法 。

而後,很不幸的告訴你,這種寫法是錯誤的,至於緣由嘛,仍是剛剛提到的知識點,exports僅僅是module.exports的一個引用,改變exports的值並不會影響到module.exports。 因此你費盡千辛萬苦簡化的代碼並無什麼卵用,最後require時引用的module.exports根本沒有像你想的那樣賦值 。

固然,這種寫法的方向是正確的,確實能夠簡化代碼,若是須要這樣寫,這裏通常有兩種寫法:

方法1:

module.exports={ .... }

這種方法直接給module.exports賦值,一了百了。

方法2:

return{ .... }

利用return返回的內容默認也至關於傳入了module.exports 。

到此爲止,咱們已經可以基本使用require來獲取模塊,exports來暴露接口。

可是,還沒結束呢,在我學習的過程當中,可不止引入了一個模塊,這個時候,引入多個模塊會有一個小問題。

好比

var a=require("modulessA");

var b=require("modulesB");

我引入了兩個模塊,一個modulesA,一個modulesB,但因爲粗心,我寫錯了第一個模塊的名字,此時獲取a模塊那一行會報錯,從而阻塞後續代碼的運行 這樣會形成很很差的影響,要知道seajs的初衷就是儘可能0阻塞 。

此處,seajs提供了require.async方法來異步獲取模塊,

var a=require.async("modulesssssA");

 此時,雖然該行會報錯,但不會影響後續代碼的執行,這就是異步加載帶來的好處,使用async時還能夠傳入回調函數來指定加載完以後執行的邏輯 。

談到異步與同步,忽然又想起一個須要注意的地方 ,那就是module.exports的賦值必須是同步完成,而不能放在回調函數裏,。

例如

setTimeout(function(){
  module.exports=...
},0);

  此時module.exports會變爲 undefined 。

  在文章的最後,還提醒你們注意到一個性能問題,那就是seajs模塊化項目以後,若是功能較多,大量的模塊js加載會形成大量請求,這顯然對項目性能是有影響的  。

  玉伯本人是推薦是用spm工具來壓縮合並這些模塊,這樣全部的模塊會合併到一個js裏,適合項目上線使用 至於spm的具體配置,本人就不詳細講解了,百度一下,你就知道。

  聽我囉嗦了半天,但願初學者能對seajs有充分的瞭解,我本人也是初次接觸,這是我學習了一天以後總結出來的一些基礎知識,適用於剛剛上手的朋友,至於大牛們,還請批評指正,畢竟個人理解也比較淺薄,不免有疏漏和表達不當的地方。

  最後還囉嗦一句! seajs和requirejs感受最大的不一樣在於seajs是按需加載,用到的時候再加載,而requirejs是提早加載,提早就將用到的模塊寫在一個數組裏一開始就加載好, 至於孰優孰劣,在下也很差評價。

相關文章
相關標籤/搜索