首頁 > web前端 > js教程 > 主體

基於RequireJS與JQuery的模組化程式設計日常問題解析_javascript技巧

WBOY
發布: 2016-05-16 15:05:41
原創
1281 人瀏覽過

由於js的程式碼邏輯越來越重,一個js檔案可能會有上千行,十分不利於開發與維護。最近把邏輯很重的js分割成模組,在一頓糾結是使用requirejs還是seajs的時候,最後還是偏向requirejs。畢竟官方文件比較專業嘛...

不過即便是有完整的官方文檔,仍然遇到不少的問題,例如jquery-ui的使用。

以下就循序漸進的講解一下我遇到的問題,以及解決的辦法。

關於AMD和CMD的理解

AMD(非同步模組定義)的典型就是requirejs,而CMD(通用模組定義)的典型是淘寶的seajs。

他們的相同點是,都會異步的載入js。但不同點是,require.js載入完會立即執行;而seajs則是等到進入主函數需要執行時才執行。

如果使用seajs初始的載入執行效率會比較高,但是在使用的過程中可能會取執行js,因此可能會出現卡頓,影響使用者體驗(由於我也沒試過,要是說錯了,別見怪)。而requirejs則是在一開始就把所有載入的js都執行,這時,如果你的模組中有一些執行方法,它們可能不會按照你想的順序執行。

因此,如果已經習慣了非同步編程,並且希望有完善的文檔推薦使用requirejs;如果是想對執行順序有特殊要求,又方便開發,那麼也可以使用seajs。

如何解決requirejs中循環依賴問題

如果你定義的某個a模組使用到了b模組,而b模組又使用了a模組,那麼就會拋出循環依賴的異常。

比如,我這裡寫了一個循環依賴的例子。

主頁:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script data-main="test.js" src="lib/require.js"></script>
</body>
</html>
登入後複製

主方法:

requirejs.config({
baseUrl: './'
});
requirejs(['js/a'],function (a){
console.log("in test");
a.testfromb();
});
登入後複製

a.js模組中,atest()方法提供b呼叫、testfromb()方法呼叫b的方法

define(function(require){
var b = require("js/b");
console.log("in a");
return {
atest:function(){
console.log("test in a");
},
testfromb:function(){
console.log("testfromb in a");
b.btest();
}
}
});
登入後複製

b模組中,呼叫了a的方法。

define(function(require){
var a = require("js/a");
console.log("in b");
return {
btest:function(){
console.log("test in b");
a.atest();
}
}
});
登入後複製

這樣相當於a呼叫了b的方法,但是b的方法依賴a的方法,這就造成了循環相依性。瀏覽器會提示錯誤:

Uncaught Error: Module name "js/a" has not been loaded yet for context: _ 
登入後複製

依照官方文件的說法,這種屬於設計的問題,應該盡量避免。那如果避免不了該怎麼辦呢?可以這樣修改b模組:

define(function(require){
// var a = require("js/a");
console.log("in b");
return {
btest:function(){
console.log("test in b");
require("js/a").atest();
}
}
});
登入後複製

這裡是等到執行atest()方法時,才載入a模組。這時,a模組很顯然已經加載完了 。可以看到輸出的資訊:

in b
a.js:3 in a
test.js:6 in test
a.js:9 testfromb in a
b.js:6 test in b
a.js:6 test in a
登入後複製

同樣的方式,修改a可能就不好使了。這時因為模組載入的順序是從b開始的。

關於循環依賴的源碼可以參考雲盤

如何在requirejs中使用jquery

如果想要使用jquery比較簡單,直接在main.js中加入對應的依賴即可:

requirejs.config({
baseUrl: './',
paths:{
'jquery':'lib/jquery'
}
});
requirejs(['jquery'],
function ($){
$('#test').html('test');
});
登入後複製

如何在requirejs中使用jquery外掛程式

對於jquery的插件,比較常見的做法都是傳入一個jquery的對象,在這個jquery對象的基礎上添加插件對應的方法。

首先需要加入jquery插件的依賴,這裡用兩個插件舉例子-jquery-ui和jquery-datatables

requirejs.config({
baseUrl: './',
paths:{
'jquery':'lib/jquery',
'jquery-ui':'lib/jquery-ui',
'jquery-dataTables':'lib/jquery.dataTables'
},
shim:{
'jquery-ui':['jquery'],
'jquery-dataTables':['jquery']
}
});
requirejs(['jquery','jquery-ui','jquery-dataTables'],
function ($){
....
});
登入後複製

由於jquery外掛都需要依賴jquery,因此可以在shim中指定依賴關係。

除了上面這種使用方法,也可以使用commonJS風格的呼叫:

define(function(require){
var $ = require('jquery');
require('jquery-ui');
require('jquery-dataTables');
//下面都是测试,可以忽略
var _test = $('#test');
_test.selectmenu({
width : 180,
change : function(event, ui) {
console.log('change');
}
});
return {
test:function(){
//测试jquery-ui
_test.append($('<option>test1</option><option>test1</option>'));
_test.selectmenu("refresh");
//测试jquery-datatables
var _table = $('table');
_table.dataTable();
}
}
});
登入後複製

不過,執行上面的程式碼,會報一個異常:

Uncaught TypeError: _table.dataTable is not a function 
登入後複製

這是因為,dataTables並不是一個require風格的模組,因此直接這樣引入,並不會執行它內部的匿名函數。可以修改它的匿名函數,傳入$對象,在最後一行:

*/
return $.fn.dataTable;
//}));原来是这样
}($)));//这里增加执行这个匿名函数,并且传入$对象。
}(window, document));
登入後複製

これもインターネットで探す方法ですが、経験不足による原理です…

サンプル コードはクラウド ディスクを参照してください。インポートされたリソースは完了していないため、エラーが報告されますが、UI プラグインが実行できたことは成功したことを意味するため、無視できます。

requirejs で jquery-ui を使用する際の問題

requirejs は js ファイルのロード直後に実行されるため、jquery ui プラグインが DOM ページを更新する必要がある場合、ページのイベントが失敗する可能性があります。

たとえば、モジュールがロードされた後、クリック イベントはページ上の特定の要素 $('#test') にバインドされます。ただし、特定の UI プラグインを使用すると、このプラグインによって DOM 要素が再描画され、テストに対応するクリック イベントが無効になります。

解決策:

•DOM 要素がレンダリングされるまでイベント バインディングを遅らせ、その後バインディングを手動でトリガーします。 •DOM要素のイベントバインディングの代わりにイベントキャプチャを使用することもできます(面倒すぎる...推奨されません)。

たとえば、DOM で再構築された JS モジュールでは、レンダリングを実行するコードは次のとおりです。


require("xxx").initEvents();


一般的なシナリオ:


たとえば、ページ上で jquery-steps UI プラグインを使用すると、ページが再レンダリングされます。これにより、最初にバインドしたイベントが無効になってしまいました。JS ページが再構築されるまでバインドを延期し、その後再度バインドすることしかできませんでした。

上記は、RequireJS と JQuery を使用したモジュラー プログラミングにおける日常の問題についての編集者の分析の全体的な説明です。これが皆さんのお役に立てば幸いです。

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板