フロントエンド開発では、最初は、スクリプト タグに数十行または数百行のコードを埋め込むことで、いくつかの基本的なインタラクティブ効果を実現できましたが、その後、js が注目を集め、jQuery、Ajax、Node.Js など、広く使用されるようになりました。 MVC や MVVM の助けを借りて、フロントエンド開発にも注目が集まっており、フロントエンド プロジェクトはますます複雑になってきていますが、JavaScript はコードを整理するのに明確な助けを提供しません。モジュールはおろか、クラスの概念さえありません。では、モジュールとは何でしょうか?
モジュールは、特定の機能を実装するファイルです。モジュールを使用すると、必要な機能に必要なモジュールをより便利に使用できます。モジュール開発は特定の規範に従う必要があります。そうしないと、すべてが台無しになってしまいます。
AMD 仕様に従って、define を使用してモジュールを定義し、require を使用してモジュールを呼び出すことができます。
現在、主によく使われている js モジュール仕様は CommonJS と AMD の 2 つです。
AMDとはAsynchronous Module Definitionのことで、中国語名は「非同期モジュール定義」を意味します。ブラウザ側でのモジュール開発の仕様であり、サーバー側ではCommonJS
モジュールが非同期でロードされ、モジュールのロードは後続のステートメントの実行に影響を与えません。特定のモジュールに依存するすべてのステートメントはコールバック関数に配置されます。
AMD は、RequireJS のプロモーション プロセス中のモジュール定義の標準化された出力です。
AMD 仕様では、グローバル変数である関数 define が 1 つだけ定義されています。関数の説明は次のとおりです:
define(id?, dependencies?, factory);
パラメータの説明:
id:指定义中模块的名字,可选;如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必须是“顶级”的和绝对的(不允许相对名字)。 依赖dependencies:是一个当前模块依赖的,已被模块定义的模块标识的数组字面量。 依赖参数是可选的,如果忽略此参数,它应该默认为["require", "exports", "module"]。然而,如果工厂方法的长度属性小于3,加载器会选择以函数的长度属性指定的参数个数调用工厂方法。 工厂方法factory,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。
モジュール名は、定義内でモジュールを一意に識別するために使用されます。これらは依存関係配列でも使用されます:
模块名是用正斜杠分割的有意义单词的字符串 单词须为驼峰形式,或者".",".." 模块名不允许文件扩展名的形式,如“.js” 模块名可以为 "相对的" 或 "顶级的"。如果首字符为“.”或“..”则为相对的模块名 顶级的模块名从根命名空间的概念模块解析 相对的模块名从 "require" 书写和调用的模块解析
require、exports、および「beta」という名前のモジュールを使用して、「alpha」という名前のモジュールを作成します:
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //Or: return require("beta").verb(); } });
require APIの概要: //m.sbmmt.com/
AMD仕様中国語版: //m.sbmmt.com/(%E4%B8%AD%E6%96%87%E7%89%88)
現在、AMD を実装するライブラリには、RequireJS、curl、Dojo、Nodules、等
CommonJSはサーバーサイドモジュールの仕様であり、Node.jsはこの仕様を採用しています。 Node.JS は、js モジュール性の概念を初めて採用しました。
CommonJS 仕様によれば、単一のファイルがモジュールです。各モジュールには個別のスコープがあります。つまり、モジュール内で定義された変数は、グローバル オブジェクトの属性として定義されない限り、他のモジュールから読み取ることができません。
モジュール変数をエクスポートする最良の方法は、 module.exports オブジェクトを使用することです。
var i = 1; var max = 30; module.exports = function () { for (i -= 1; i++ < max; ) { console.log(i); } max *= 1.1; };
上記のコードは、モジュールの外部通信と内部通信の間のブリッジである module.exports オブジェクトを通じて関数を定義します。
require メソッドを使用してモジュールをロードします。このメソッドはファイルを読み取って実行し、最後にファイル内の module.exports オブジェクトを返します。
CommonJS 仕様: //m.sbmmt.com/
RequireJS は、AMD 仕様の創設者でもある James Burke によって作成されました。
define メソッドはモジュールを定義するために使用されます。RequireJS では、各モジュールを別のファイルに配置する必要があります。
RequireJS と Sea.js は両方ともモジュール ローダーであり、モジュール開発の概念を提唱しており、その中心的な価値は JavaScript のモジュール開発をシンプルかつ自然にすることです。
SeaJS と RequireJS の最大の違い:
SeaJS のモジュールに対する態度は遅延実行ですが、RequireJS のモジュールに対する態度は事前実行です
理解できませんか?写真とテキスト付きのこの記事をご覧ください: //m.sbmmt.com/
RequireJS API: //m.sbmmt.com/
RequireJS の使用方法: //m.sbmmt.com /
想像してみてください。Web ページに大量の JS ファイルがある場合、ブラウザはページをダウンロードするときに最初に JS ファイルをロードするため、さらに多くのファイルがある場合、Web ページのレンダリングが停止します。ブラウザが応答を失う可能性があります。次に、js ファイルの依存関係を確保する必要があります。依存関係が複雑になると、コードの作成と保守が困難になります。
RequireJS は、次の 2 つの問題を解決するために生まれました:
(1)实现js文件的异步加载,避免网页失去响应; (2)管理模块之间的依赖性,便于代码的编写和维护。
RequireJS ファイルのダウンロード: //m.sbmmt.com/
CMD (共通モジュール定義) 共通モジュール定義。この仕様は、モジュールの基本的な記述形式と基本的な対話ルールを明確にします。この基準は国内で開発されました。 AMD はフロントエンドに依存しており、CMD はオンデマンドでロードされます。
CMD 仕様では、モジュールはファイルです。コードの記述形式は以下の通りです:
define(factory);
ファクトリーが関数の場合、モジュールの構築メソッドを意味します。この構築方法を実行することで、モジュールが提供するインターフェースを取得することができます。ファクトリ メソッドが実行されると、デフォルトで、require、exports、module の 3 つのパラメータが渡されます。
define(function(require, exports, module) { // 模块代码 });
require は他のモジュールをインポートできるパラメータであり、export はモジュール内の一部のプロパティとメソッドをエクスポートできます。
CMD仕様アドレス: //m.sbmmt.com/
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。 CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
依存モジュールについては、AMDが先行して実行され、CMDは遅延して実行されます。
AMD:提前执行(异步加载:依赖先执行)+延迟执行 CMD:延迟执行(运行到需加载,根据顺序执行)
CMD は近くの依存関係を主張し、AMD は手前の依存関係を主張します。次のコードを見てください:
// 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() ... })
另外一个区别是:
AMD:API根据使用范围有区别,但使用同一个api接口 CMD:每个API的职责单一
AMD的优点是:异步并行加载,在AMD的规范下,同时异步加载是不会产生错误的。
CMD的机制则不同,这种加载方式会产生错误,如果能规范化模块内容形式,也可以
jquery1.7以上版本会自动模块化,支持AMD模式:主要是使用define函数,sea.js虽然是CommonJS规范,但却使用了define来定义模块
所以jQuery已经自动模块化了
seajs.config({ 'base':'/', 'alias':{ 'jquery':'jquery.js'//定义jQuery文件 } });
define函数和AMD的define类似:
define(function(require, exports, module{ //先要载入jQuery的模块 var $ = require('jquery'); //然后将jQuery对象传给插件模块 require('./cookie')($); //开始使用 $.cookie方法 });
引入sea.js的库
如何变成模块?
define
3.如何调用模块?
-exports -sea.js.use
4.如何依赖模块?
-require <script type="text/javascript"> define(function (require,exports,module) { //exports : 对外的接口 //requires : 依赖的接口 require('./test.js');//如果地址是一个模块的话,那么require的返回值就是模块中的exports })
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>鼠标拖拽的模块化开发实践</title> <style type="text/css"> #p1{ width:200px; height:200px; background:black; position:absolute; display:none;} #p2{ width:30px; height:30px; background:yellow; position:absolute; bottom:0; right:0;} #p3{ width:100px; height:100px; background:blue; position:absolute; right:0; top:0;} </style> <script type="text/javascript" src="./sea.js"></script> <script type="text/javascript"> //A同事 : seajs.use('./main.js'); </script> </head> <body> <input type="button" value="确定" id="input1" /> <p id="p1"> <p id="p2"></p> </p> <p id="p3"></p> </body> </html>
//A同事写的main.js: define(function (require,exports,module) { var oInput = document.getElementById('input1'); var op1 = document.getElementById('p1'); var op2 = document.getElementById('p2'); var op3 = document.getElementById('p3'); require('./drag.js').drag(op3); oInput.onclick = function () { op1.style.display = 'block'; require('./scale.js').scale(op1,op2); require.async('./scale.js', function (ex) { ex.scale(op1,op2); }) } });
//B同事写的drag.js: define(function(require,exports,module){ function drag(obj){ var disX = 0; var disY = 0; obj.onmousedown = function(ev){ var ev = ev || window.event; disX = ev.clientX - obj.offsetLeft; disY = ev.clientY - obj.offsetTop; document.onmousemove = function(ev){ var ev = ev || window.event; var L = require('./range.js').range(ev.clientX - disX , document.documentElement.clientWidth - obj.offsetWidth , 0 ); var T = require('./range.js').range(ev.clientY - disY , document.documentElement.clientHeight - obj.offsetHeight , 0 ); obj.style.left = L + 'px'; obj.style.top = T + 'px'; }; document.onmouseup = function(){ document.onmousemove = null; document.onmouseup = null; }; return false; }; } exports.drag = drag;//对外提供接口 });
//C同事写的scale.js: define(function(require,exports,module){ function scale(obj1,obj2){ var disX = 0; var disY = 0; var disW = 0; var disH = 0; obj2.onmousedown = function(ev){ var ev = ev || window.event; disX = ev.clientX; disY = ev.clientY; disW = obj1.offsetWidth; disH = obj1.offsetHeight; document.onmousemove = function(ev){ var ev = ev || window.event; var W = require('./range.js').range(ev.clientX - disX + disW , 500 , 100); var H = require('./range.js').range(ev.clientY - disY + disH , 500 , 100); obj1.style.width = W + 'px'; obj1.style.height = H + 'px'; }; document.onmouseup = function(){ document.onmousemove = null; document.onmouseup = null; }; return false; }; } exports.scale = scale; });
// D同事的range.js--限定拖拽范围 define(function(require,exports,module){ function range(iNum,iMax,iMin){ if( iNum > iMax ){ return iMax; } else if( iNum < iMin ){ return iMin; } else{ return iNum; } } exports.range = range; });
require.config是用来定义别名的,在paths属性下配置别名。然后通过requirejs(参数一,参数二);参数一是数组,传入我们需要引用的模块名,第二个参数是个回调函数,回调函数传入一个变量,代替刚才所引入的模块。
//别名配置 requirejs.config({ paths: { jquery: 'jquery.min' //可以省略.js } }); //引入模块,用变量$表示jquery模块 requirejs(['jquery'], function ($) { $('body').css('background-color','red'); });
引入模块也可以只写require()。requirejs通过define()定义模块,定义的参数上同。在此模块内的方法和变量外部是无法访问的,只有通过return返回才行.
define(['jquery'], function ($) {//引入jQuery模块 return { add: function(x,y){ return x + y; } }; });
将该模块命名为math.js保存。
require(['jquery','math'], function ($,math) { console.log(math.add(10,100));//110 });
如果定义的模块不依赖其他模块,则可以:
define(function () { return { name: "trigkit4", age: "21" } });
AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。
以上就是详解JavaScript模块化开发的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!