ホームページ > 記事 > ウェブフロントエンド > RequireJS および JQuery_javascript スキルに基づいたモジュラー プログラミングにおける日常の問題の分析
js のコード ロジックはますます重くなるため、js ファイルには数千行が含まれる場合があり、これは開発やメンテナンスにとって非常に不利です。最近、ロジックの重い JS をモジュールに分割しています。requirejs と seajs のどちらを使用するか悩んだのですが、最終的には requirejs を使用することにしました。やっぱり公式文書のほうが専門的ですね…
しかし、完全な公式ドキュメントがあっても、jquery-ui の使用など、依然として多くの問題に遭遇します。
以下は、私が遭遇した問題とその解決策を段階的に説明したものです。
AMD と CMD の理解
AMD(非同期モジュール定義)の代表例はrequirejs、CMD(共通モジュール定義)の代表例はタオバオのseajsです。
これらに共通しているのは、すべて js を非同期でロードすることです。ただし、require.js はロード直後に実行されるのに対し、seajs は main 関数に入って実行する必要があるまで実行されないという点が異なります。
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 モジュールでは、test() メソッドが 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(); } } });
ここでは、モジュールをロードする前に、test() メソッドが実行されるまで待機します。この時点でモジュール 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 の 2 つのプラグインを示します。
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));
This is also a method of searching on the Internet, but the principle is due to lack of experience....
You can refer to the cloud disk for the sample code. Since the imported resources are not complete, an error will be reported and can be ignored. Because being able to execute the UI plug-in means it has been successful.
Problems using jquery-ui with requirejs
Since requirejs will be executed immediately after loading the js file, if your jquery ui plug-in needs to refresh the DOM page, it may cause the page's events to fail.
For example, after your module is loaded, a click event is bound to a certain element $('#test') on the page. However, if a certain UI plug-in is used, the plug-in will re-render the DOM element, and the click event corresponding to test will become invalid.
Solution:
•Delay event binding until the DOM element is rendered and then manually trigger the binding;
•Event capture can also be used instead of event binding of DOM elements (too troublesome...not recommended).
For example, in the DOM reconstructed JS module, the code that executes rendering is as follows:
require("xxx").initEvents();
Common scenarios:
For example, I use the jquery-steps UI plug-in on the page, which will re-render the page. This caused the events I originally bound to become invalid... I could only postpone binding until the js page was reconstructed and then bind again.
The above is the entire description of the editor’s analysis of daily problems in modular programming with RequireJS and JQuery. I hope it will be helpful to everyone!