目錄javascript
@(工程化和項目管理)css
<script type="text/javascript" src="module1.js"></script> <script type="text/javascript" src="module2.js"></script> <script type="text/javascript" src="module3.js"></script> <script type="text/javascript" src="module4.js"></script>
function fun1(){ //... } function fun2(){ //... } //上面的函數fun1,fun2組成了一個模塊,使用的時候直接調用某個函數就好了。
var module1 = new Object({ count : 0, fun1 : function (){ //... }, fun2 : function (){ //... } }); //這個裏面的fun1和fun2都封裝在一個賭俠寧裏,能夠經過對象.方法的形式進行調用; module1.fun1();
var module1 = (function(){ var count = 0; var fun1 = function(){ //... } var fun2 = function(){ //... } //將想要暴露的內容放置到一個對象中,經過return返回到全局做用域。 return{ fun1:fun1, fun2:fun2 } })() //這樣的話只能在全局做用域中讀到fun1和fun2,可是讀不到變量count,也修改不了了。 //問題:當前這個模塊依賴另外一個模塊怎麼辦?
var module1 = (function (mod){ mod.fun3 = function () { //... }; return mod; })(module1); //爲module1模塊添加了一個新方法fun3(),而後返回新的module1模塊。 //引入jquery到項目中; var Module = (function($){ var _$body = $("body"); // we can use jQuery now! var foo = function(){ console.log(_$body); // 特權方法 } // Revelation Pattern return { foo: foo } })(jQuery) Module.foo();
Browserify : 瀏覽器端html
exports.xxx = value // 經過module.exports指定暴露的對象value module.exports = value
var module = require('模塊相對路徑')
exports = {Obj}
,暴露的API須做爲此對象的屬性。exports本質是引入了module.exports的對象。不能直接將exports變量指向一個值,由於這樣等於切斷了exports與module.exports的聯繫。exports=module.exports={Obj}
//結構以下 |-modules |-module1.js//待引入模塊1 |-module2.js//待引入模塊2 |-module3.js//待引入模塊3 |-app.js//主模塊 |-package.json { "name": "commonjsnode", "version": "1.0.0" }
3.下載第三方模塊:舉例express
npm i express --save
java
// module1 // 使用module.exports = value向外暴露一個對象 module.exports = { name: 'this is module1', foo(){ console.log('module1 foo()'); } } // module2 // 使用module.exports = value向外暴露一個函數 module.exports = function () { console.log('module2()'); } // module3 // 使用exports.xxx = value向外暴露一個對象 exports.foo = function () { console.log('module3 foo()'); }; exports.bar = function () { console.log('module3 bar()'); }; exports.name = 'this is module3' //app.js文件 var uniq = require('uniq'); //引用模塊 let module1 = require('./modules/module1'); let module2 = require('./modules/module2'); let module3 = require('./modules/module3'); //使用模塊 module1.foo(); module2(); module3.foo(); module3.bar(); module3.name;
|-js |-dist //打包生成文件的目錄 |-src //源碼所在的目錄 |-module1.js |-module2.js |-module3.js |-app.js //應用主源文件 |-index.html //瀏覽器上的頁面 |-package.json { "name": "browserify-test", "version": "1.0.0" }
browserify js/src/app.js -o js/dist/bundle.js
<script type="text/javascript" src="js/dist/bundle.js"></script>
若是是瀏覽器環境,要從服務器端加載模塊,這時就必須採用非同步模式,所以瀏覽器端通常採用AMD規範。node
define([依賴模塊名], function(){return 模塊對象})
引入模塊: require(['模塊1', '模塊2', '模塊3'], function(m1, m2){//使用模塊對象})
jquery
define(function (require, exports, module) { var reqModule = require("./someModule"); requModule.test(); exports.asplode = function () { //someing } });
require([module], callback);
管理模塊之間的依賴性,便於代碼的編寫和維護。git
js/libs/require.js
|-js |-libs |-require.js // 引入的require.js |-modules |-alerter.js |-dataService.js |-main.js |-index.html
define(['myLib'], function(myLib){ function foo(){ myLib.doSomething(); } // 暴露模塊 return {foo : foo}; }); //當require()函數加載上面這個模塊的時候,就會先加載myLib.js文件。
// dataService.js define(function () { let msg = 'this is dataService' function getMsg() { return msg.toUpperCase() } return {getMsg} }) // alerter.js define(['dataService', 'jquery'], function (dataService, $) { let name = 'Tom2' function showMsg() { $('body').css('background', 'gray') alert(dataService.getMsg() + ', ' + name) } return {showMsg} })
(function () { //配置 require.config({ //基本路徑 baseUrl: "js/", //模塊標識名與模塊路徑映射 paths: { "alerter": "modules/alerter",//此處不能寫成alerter.js,會報錯 "dataService": "modules/dataService", } }) //引入使用模塊 require( ['alerter'], function(alerter) { alerter.showMsg() }) })()
<script data-main="js/main" src="js/libs/require.js"></script>
js/libs/jquery-1.10.1.js
paths: { 'jquery': 'libs/jquery-1.10.1' }
define(['dataService', 'jquery'], function (dataService, \$) { var name = 'xfzhang' function showMsg() { $('body').css({background : 'red'}) alert(name + ' '+dataService.getMsg()) } return {showMsg} })
js/libs/angular.js
// main.js中配置 (function () { //配置 require.config({ //基本路徑 baseUrl: "js/", //模塊標識名與模塊路徑映射 paths: { //第三方庫做爲模塊 'jquery' : './libs/jquery-1.10.1', 'angular' : './libs/angular', //自定義模塊 "alerter": "./modules/alerter", "dataService": "./modules/dataService" }, /* 配置不兼容AMD的模塊 exports : 指定與相對應的模塊名對應的模塊對象 */ shim: { 'angular' : { exports : 'angular' } } }) //引入使用模塊 require( ['alerter', 'angular'], function(alerter, angular) { alerter.showMsg() console.log(angular); }) })()
定義暴露模塊:es6
// 沒有依賴的模塊 define(function(require, module, exports){ let value = 'xxx'; //經過require引入依賴模塊 //經過module.exports/exports來暴露模塊 exports.xxx = value module.exports = value }) // 有依賴的模塊 define(function(require, exports, module){ //引入依賴模塊(同步) var module2 = require('./module2') //引入依賴模塊(異步) require.async('./module3', function (m3) { ...... }) //暴露模塊 exports.xxx = value })
使用模塊seajs.use(['模塊1', '模塊2'])github
js/libs/sea.js
define() exports module.exports
require()
seajs.use()
|-js |-libs |-sea.js |-modules |-module1.js |-module2.js |-module3.js |-module4.js |-main.js |-index.html
define(function (require, exports, module) { //內部變量數據 var data = 'this is module1' //內部函數 function show() { console.log('module1 show() ' + data) } //向外暴露 exports.show = show })
define(function (require, exports, module) { module.exports = { msg: 'I Will Back' } })
define(function (require, exports, module) { const API_KEY = 'abc123' exports.API_KEY = API_KEY })
define(function (require, exports, module) { //引入依賴模塊(同步) var module2 = require('./module2'); function show() { console.log('module4 show() ' + module2.msg) } exports.show = show //引入依賴模塊(異步) require.async('./module3', function (m3) { console.log('異步引入依賴模塊3 ' + m3.API_KEY) }) })
define(function (require) { var m1 = require('./module1') var m4 = require('./module4') m1.show() m4.show() })
<script type="text/javascript" src="js/libs/sea.js"></script> <script type="text/javascript"> seajs.use('./js/modules/main') </script>
// math.js export const add = function (a, b) { return a + b } export const subtract = function (a, b) { return a - b }
// main.js import { add, subtract } from './math.js' add(1, 2) substract(3, 2)
export default 對象
export var xxx = value1 export let yyy = value2 // 暴露一個對象 var xxx = value1 let yyy = value2 export {xxx, yyy}
import xxx from '模塊路徑/模塊名'
import {xxx, yyy} from '模塊路徑/模塊名' import * as module1 from '模塊路徑/模塊名'
export不止能夠導出函數,還能夠導出,對象、類、字符串等等;express
export const obj = {test1: ''} export const test = '' export class Test { constuctor() { } } // 或者,直接在暴露的地方定義導出函數或者變量 export let foo = ()=>{console.log('fnFoo');return "foo"},bar="stringBar"
let a=1 let b=2 let c=3 export { a,b,c }
// test.js let a = 1 let b = 2 let c = 3 export { a as test, b, c }; import { test, b, c } from './test.js' // 改變命名後只能寫 as 後的命名
// test.js let a = 1 let b = 2 let c = 3 export { a as test, b, c }; // lib.js引入test.js的內容 export * from './test.js' // 引入 import {test,b,c} from './lib.js'
// test.js export default function () { console.log('hello world') } //引入 import say from './test.js' // 這裏能夠指定任意變量名 say() // hello world
import $ from 'jQuery' // 加載jQuery 庫 import _ from 'lodash' // 加載 lodash import moment from 'moment' // 加載 moment
// main.js import { add, subtract } from './test' // 對於export default 導出的 import say from './test'
import {add as sum, subtract} from './test' sum (1, 2)
// math.js export const add = function (a, b) { return a + b } export const subtract = function (a, b) { return a - b } //引入 import * as math from './test.js' math.add(1, 2) math.subtract(1, 2)
{ "name" : "es6-babel-browserify", "version" : "1.0.0" }
npm install babel-cli browserify -g npm install babel-preset-es2015 --save-dev
{ "presets": ["es2015"] }
// js/src/module1.js export function foo() { console.log('module1 foo()'); }; export let bar = function () { console.log('module1 bar()'); }; export const DATA_ARR = [1, 3, 5, 1]; // js/src/module2.js let data = 'module2 data'; function fun1() { console.log('module2 fun1() ' + data); }; function fun2() { console.log('module2 fun2() ' + data); }; export {fun1, fun2}; // js/src/module3.js export default { name: 'Tom', setName: function (name) { this.name = name } } // js/src/app.js import {foo, bar} from './module1' import {DATA_ARR} from './module1' import {fun1, fun2} from './module2' import person from './module3' import $ from 'jquery' //引入完畢 $('body').css('background', 'red') foo() bar() console.log(DATA_ARR); fun1() fun2() person.setName('JACK') console.log(person.name);
<script type="text/javascript" src="js/lib/bundle.js"></script>
npm install jquery@1 --save
import $ from 'jquery' $('body').css('background', 'red')
模塊化方案 | 優勢 | 缺點 |
---|---|---|
commonJS | 複用性強; 使用簡單; 實現簡單; |
有很多能夠拿來即用的模塊,生態不錯; 同步加載不適合瀏覽器,瀏覽器的請求都是異步加載; 不能並行加載多個模塊。 |
AMD | 異步加載適合瀏覽器 | 可並行加載多個模塊; 模塊定義方式不優雅,不符合標準模塊化 |
ES6 | 可靜態分析,提早編譯 | 面向將來的標準; 瀏覽器原生兼容性差,因此通常都編譯成ES5; 目前能夠拿來即用的模塊少,生態差 |
// CMD define(function(require, exports, module) { var a = require('./a'); a.doSomething() // 此處略去 100 行 var b = require('./b') // 依賴能夠就近書寫 b.doSomething() // ... }) // AMD 默認推薦的是 define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好 a.doSomething() // 此處略去 100 行 b.doSomething() ...})