JavaScript模塊化開發(fā)之SeaJS
前言
SeaJS是一個(gè)遵循CommonJS規(guī)范的JavaScript模塊加載框架,可以實(shí)現(xiàn)JavaScript的模塊化開發(fā)及加載機(jī)制。使用SeaJS可以提高JavaScript代碼的可讀性和清晰度,解決目前JavaScript編程中普遍存在的依賴關(guān)系混亂和代碼糾纏等問題,方便代碼的編寫和維護(hù)。
SeaJS本身遵循KISS(Keep it Simple,Stupid)理念進(jìn)行開發(fā),后續(xù)的幾個(gè)版本更新也都是吵著這個(gè)方向邁進(jìn)。
如何使用SeaJS
下載及安裝在這里不贅述了,不了解的請(qǐng)查詢官網(wǎng)。
基本開發(fā)原則
•一切皆為模塊:SeaJS中的模塊概念有點(diǎn)類似于面向?qū)ο笾械念?-模塊可以擁有數(shù)據(jù)和方法,數(shù)據(jù)和方法可以定義為公共或私有,公共數(shù)據(jù)和方法可以供別的模塊調(diào)用。
•每個(gè)模塊應(yīng)該都定義在一個(gè)單獨(dú)的js文件中,即一個(gè)對(duì)應(yīng)一個(gè)模塊。
模塊的定義和編寫
模塊定義函數(shù)define
SeaJS中使用define函數(shù)定義一個(gè)模塊。define可以接收三個(gè)參數(shù):
/** * Defines a module. * @param {string=} id The module id. * @param {Array.|string=} deps The module dependencies. * @param {function()|Object} factory The module factory function. */ fn.define = function(id, deps, factory) { //code of function… }
define可以接收的參數(shù)分別是模塊ID,依賴模塊數(shù)組及工廠函數(shù)。
•如果只有一個(gè)參數(shù),則賦值給factory
•如果有兩個(gè)參數(shù),第二個(gè)賦值給factory,第一個(gè)如果是數(shù)組則賦值給deps,否則賦值給id
•如果有三個(gè)參數(shù),則分別賦值
但是,包括SeaJS官網(wǎng)示例在內(nèi)幾乎所有用到define的地方都只傳遞一個(gè)工廠函數(shù)進(jìn)去,類似于如下代碼:
define(function(require,exports,module){ //code of the module })
個(gè)人建議遵循SeaJS官方示例的標(biāo)準(zhǔn),用一個(gè)參數(shù)的define定義模塊。那么id和deps會(huì)怎么處理呢?
id是一個(gè)模塊的標(biāo)識(shí)字符串,define只有一個(gè)參數(shù)時(shí),id會(huì)被默認(rèn)賦值為此js文件的絕對(duì)路徑。如example.com下的a.js文件中使用define定義模塊,則這個(gè)模塊的ID會(huì)賦值為 http://example.com/a.js ,沒有特別的必要建議不要傳入id。deps一般也不需要傳入,需要用到的模塊用require加載即可。
工廠函數(shù)factory解析
工廠函數(shù)是模塊的主體和重點(diǎn)。它的三個(gè)參數(shù)分別是:
•require:模塊加載函數(shù),用于記載依賴模塊
•exports:接口點(diǎn),將數(shù)據(jù)或方法定義在其上則將其暴露給外部調(diào)用
•module:模塊的元數(shù)據(jù)
這三個(gè)參數(shù)可以根據(jù)需要選擇是否需要顯示指定。
module是一個(gè)對(duì)象,存儲(chǔ)了模塊的元信息,具體如下:
•module.id:模塊的ID
•module.dependencies:一個(gè)數(shù)組,存儲(chǔ)了此模塊依賴的所有模塊的ID列表。
•module.exports:與exports指向同一個(gè)對(duì)象
三種編寫模塊的模式
第一種是基于exports的模式:
define(function(require,exports,module){ var a=require('a'); var b=require('b'); //引入模塊 var data1=1; //私有數(shù)據(jù) var fun1=function(){//私有方法 return a.run(data1); } exports.data2=2; //公有數(shù)據(jù) exports.fun2=function(){ return 'hello'; } })
上面是一種比較“正宗”的模塊定義模式。除了講公共數(shù)據(jù)和方法附加在exports上,也可以直接返回一個(gè)對(duì)象表示模塊,如下面的代碼與上面的代碼功能相同:
define(function(require){ var a=require('a'); var b=require('b'); //引入模塊 var data1=1; var fun1=function(){ return a.run(data1); } return{ data2:2, fun2:function(){ return 'hello'; } } })
如果模塊定義沒有其他代碼,只返回一個(gè)對(duì)象,還可以有如下簡(jiǎn)化寫法:
define({ data2:2, fun2:function(){ return 'hello'; } })
第三種寫法對(duì)于定義純JSON數(shù)據(jù)的模塊非常合適。
根據(jù)應(yīng)用場(chǎng)景的不同,SeaJS提供了三個(gè)載入模塊的API,分別是:seajs.use,require和require.async。
seajs.use
seajs.use主要用于載入入口模塊。入口模塊相當(dāng)于C語(yǔ)言的main函數(shù),同時(shí)也是整個(gè)模塊依賴樹的根。seajs.use
的用法如下:
//第一模式 seajs.use('./a'); //回調(diào)模式 seajs.use('./a',function(a){ a.run(); }) //多模塊模式 seajs.use(['./a','./b'],function(a,b){ a.run(); b.run(); })
其中多模塊的用法和KISSY中的模塊加載方法類似,不虧是一個(gè)人寫的啊!
一般seajs.use只用在頁(yè)面載入入口模塊,SeaJS會(huì)順著入口模塊解析所有依賴模塊并將它們加載。如果入口模塊只有一個(gè),也可以通過給引入seajs的script標(biāo)簽加入“data-main”屬性來省略seajs.use,例如一下寫法:
<!DOCTYPE HTML> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>TinyApp</title> </head> <body> <p class="content"></p> <script src="./sea.js" data-main="./init"></script> </body> </html> require
require是seajs主要的模塊加載方法,當(dāng)在一個(gè)模塊中需要用到其他模塊時(shí)一般用require加載:
var m=require('./a'); require.async
上文說過seajs會(huì)在html頁(yè)面打開時(shí)通過靜態(tài)分析一次性記載所有需要的js文件,如果想要某個(gè)js文件在用時(shí)才加載,可以使用require.async。
這樣只有在用到這個(gè)模塊時(shí),對(duì)應(yīng)的js文件才會(huì)被下載,也就實(shí)現(xiàn)了JavaScript代碼的按需加載。
SeaJS的全局配置
seajs提供了一個(gè)seaj.configd的方法可以設(shè)置全局配置,接收一個(gè)表示全局配置的配置對(duì)象,具體方法如下:
seajs.config({ base:'path', alias:{ 'app':'path/app/' }, charset:'utf-8', timeout:20000, debug:false })
其中,
•base表示基址路徑
•alias可以對(duì)較長(zhǎng)的常用路徑設(shè)置縮寫
•charset表示下載js時(shí)script標(biāo)簽的charset屬性。
•timeout表示下載文件的最大時(shí)長(zhǎng),以毫秒為單位。
Seajs如何與現(xiàn)有的JS庫(kù)配合使用
要將現(xiàn)有的JS庫(kù)與seajs一起使用,只需根據(jù)seajs的模塊定義規(guī)則對(duì)現(xiàn)有庫(kù)進(jìn)行一個(gè)封裝。例如,下面是對(duì)jQuery的封裝方法:
define(function(){ /* 此處為jquery源碼 */ })
一個(gè)完整的例子:
上文說了那么多,知識(shí)點(diǎn)比較分散,所以最后我打算用一個(gè)完整的SeaJS例子把這些知識(shí)點(diǎn)串起來,方便朋友們歸納回顧。這個(gè)例子包含如下文件:
•index.html 主頁(yè)面
•sea.js
•jquery.js
•init.js init模塊,入口模塊,依賴data、jquery、style三個(gè)模塊,又主頁(yè)面載入
•data.js data模塊,純json數(shù)據(jù)模塊
•style.css css樣式表
html: <!DOCTYPE HTML> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="content"> <p class="author"></p> <p class="blog"><a href="#">Blog</a></p> </div> <script src="sea.js"></script> <script> seajs.use('init'); </script> </body> </html> javascript: //init.js define(function(require, exports, module) { var $ = require('./jquery'); var data = require('./data'); var css = require('./style.css'); $('.author').html(data.author); $('.blog').attr('href', data.blog); }); //data.js define({ author: 'ZhangYang', blog: 'http://blog.codinglabs.org' }); css: .author{color:red;font-size:10pt;} .blog{font-size:10pt;}
請(qǐng)注意:
1.請(qǐng)講jquery.js源碼文件包含在seajs模塊加載代碼中;
2.在Sea.js < 2.3.0版本之前是可以加載css文件的,新版本中此功能移除,為了兼容考慮,加載css功能將作為一個(gè)插件存在。
使用方法
•可以在sea.js標(biāo)簽后引入這個(gè)插件使用
•也可以將插件代碼混入sea.js當(dāng)中
•和seajs-style的區(qū)別 •seajs-css是使 Sea.js 能夠加載一個(gè)css文件,和link標(biāo)簽一樣
•seajs-style是指提供一個(gè)seajs.importStyle方法用于加載一段 css 字符串
以上內(nèi)容是小編給大家分享的JavaScript模塊化開發(fā)之SeaJS,希望對(duì)大家學(xué)習(xí)javascript模塊化開發(fā)有所幫助,謝謝大家一直以來對(duì)腳本之家網(wǎng)站的支持。!
- 在Html中使用Requirejs進(jìn)行模塊化開發(fā)實(shí)例詳解
- 使用requirejs模塊化開發(fā)多頁(yè)面一個(gè)入口js的使用方式
- 詳解JavaScript模塊化開發(fā)
- JavaScript的模塊化開發(fā)框架Sea.js上手指南
- Seajs 簡(jiǎn)易文檔 提供簡(jiǎn)單、極致的模塊化開發(fā)體驗(yàn)
- 了解Javascript的模塊化開發(fā)
- javascript 構(gòu)建模塊化開發(fā)過程解析
- 深入探尋seajs的模塊化與加載方式
- seajs和requirejs模塊化簡(jiǎn)單案例分析
- 基于RequireJS和JQuery的模塊化編程日常問題解析
- 基于RequireJS和JQuery的模塊化編程——常見問題全面解析
- JavaScript 模塊化開發(fā)實(shí)例詳解【seajs、requirejs庫(kù)使用】
相關(guān)文章
javascript設(shè)計(jì)模式之模塊模式學(xué)習(xí)筆記
這篇文章主要為大家詳細(xì)介紹了javascript設(shè)計(jì)模式之模塊模式學(xué)習(xí)筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02TypeScript中type和interface的區(qū)別及注意事項(xiàng)
type的類型別用可以用戶其他的類型,比如聯(lián)合類型、元祖類型、基本類型,interface不行,下面這篇文章主要給大家介紹了關(guān)于TypeScript中type和interface的區(qū)別及注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2022-10-10基于JS實(shí)現(xiàn)帶并發(fā)限制的異步調(diào)度器
這篇文章主要為大家詳細(xì)介紹了如何基于JS實(shí)現(xiàn)帶并發(fā)限制的異步調(diào)度器,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考下2023-05-05JavaScript常見繼承模式實(shí)例小結(jié)
這篇文章主要介紹了JavaScript常見繼承模式,結(jié)合實(shí)例形式總結(jié)分析了javascript原型鏈繼承、構(gòu)造函數(shù)繼承、組合繼承、原型式繼承、寄生式繼承等相關(guān)實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下2019-01-01如何使用bootstrap框架 bootstrap入門必看!
如何使用bootstrap?這篇文章就是告訴大家如何使用bootstrap框架,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04javascript解析xml實(shí)現(xiàn)省市縣三級(jí)聯(lián)動(dòng)的方法
這篇文章主要介紹了javascript解析xml實(shí)現(xiàn)省市縣三級(jí)聯(lián)動(dòng)的方法,涉及javascript針對(duì)節(jié)點(diǎn)的操作與XML文件解析的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07用js實(shí)現(xiàn)每隔一秒刷新時(shí)間的實(shí)例(含年月日時(shí)分秒)
下面小編就為大家?guī)硪黄胘s實(shí)現(xiàn)每隔一秒刷新時(shí)間的實(shí)例(含年月日時(shí)分秒)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10淺談對(duì)于“不用setInterval,用setTimeout”的理解
這篇文章主要介紹了淺談對(duì)于“不用setInterval,用setTimeout”的理解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08