近來參與的一個GIS項目,類似黑闆系統。所有功能都往GIS上展示,是以不可能預先寫好全部的JS引用,而采用類似動态注冊的方式。我就應用了一回JS的AMD規範。
AMD規範最大的好處,我認為是解決了JS依賴的問題。這個JS檔案,需要依賴另一個JS檔案的内容。如果大家都在一個頁面上引用,當然沒有問題。但動态取舍的情況就不一樣了。
利用AMD規範能夠較好地解決這個問題。凡符合AMD規範,或者在裡面注冊的,都可以友善地動态引用。而不必預先聲明在頁面上。詳細步驟和注意事項如下:
一、注冊符合AMD規範或能應用AMD規範的的js檔案
js/modules.js,各路js注冊檔案,要能被别人引用,首先要在這裡注冊。一般命名為main.js,但這個不是固定的,像本例就命名為modules.js。
require.config({//require.config是require.js裡定義的,套路如此,知道就行
baseUrl: "js",//咱們要使用的這些js檔案,從這個目錄開始算
shim: {//非AMD規範JS檔案聲明,裡面這3個都不符合AMD規範。testObj,CanvasWindy都是函數名
'test': {
deps: [],
exports: 'testObj'//函數名
},
'gWindy':{
deps: [],
exports: 'CanvasWindy'//函數名
},
'gCurrent':{
deps: [],
exports: 'CanvasWindy'//函數名
}
},
paths: {//給每一個js檔案賦一個ID,注意"global/windy/Windy"等同于"global/windy/Windy.js",檔案字尾被省略了
"gWindy": "global/windy/Windy",//這些檔案,根目錄是/js(對應上面的baseUrl: "js")
"gCurrent": "global/windy/Current",
"wind":"global/windy/wind",
"current":"global/windy/currentLoader",
"test": "testAMD"
});
js/testAMD.js
var testObj = (function(){
return {
hi:function(){
alert("Hello World!");
}
};
})();
二、聲明require.js
<script data-main="./js/modules" src="./libs/require.js"></script>
require.js是AMD規範庫。data-main訓示注冊檔案是./js/modules.js。
注意,在頁面上放置這個require.js,很可能會引起沖突。require裡面,其實就定義了一個define函數。但現在許多js庫都有同名函數,極其容易引起沖突。怎麼辦呢?我用
<iframe>
來解決。将聲明require.js放置在一個相對比較幹淨,不會引起沖突的iframe裡,然後通過iframe引用它就行了。比如:
var require = window.top.require;
function wind(){
require(['wind'],function(windjs){
windjs.go(containerId,viewer,window,Cesium);
});
}
三、引用AMD規範js
var require = window.top.require;
function wind(){
require(['wind'],function(windjs){//‘wind ’是一個ID,在modules.js裡定義了,參考上面例子
windjs.go(containerId,viewer,window,Cesium);
});
}
附錄、一個符合AMD規範的js
js/global/windy/wind.js
define(['gWindy'],function(CanvasWindy){
function go(containerId,viewer,window,Cesium) {
var canvasId = "windycanvas";
var windy = null,windycanvas=null;
var document = window.document;
...
}
return {
go:go
};
});
注意裡面有用到window,document這些對象的話,它們是相對require.js所在頁面而言的。在本例子中,require.js放置在了最外層的頁面(window.top),而使用AMD規範的JS如果想用本頁面對應的window這類對象的話,最好通過參數傳進去。