프론트엔드 개발에서는 처음에는 스크립트 태그에 수십 줄, 수백 줄의 코드를 삽입하여 몇 가지 기본적인 대화형 효과를 얻을 수 있었지만 나중에는 jQuery, Ajax, JS 등이 주목을 받으며 널리 사용되었습니다. Node.Js, MVC, MVVM 등도 프론트엔드 개발에 관심을 가져왔고 프론트엔드 프로젝트를 점점 더 복잡하게 만들었습니다. 그러나 JavaScript는 코드 구성에 뚜렷한 도움을 제공하지 않으며 심지어는 없습니다. 모듈은 말할 것도 없고 클래스의 개념도 있는데, 모듈이란 무엇일까요?
모듈이란 특정 기능을 구현한 파일을 말하며, 모듈을 사용하면 다른 사람의 코드를 보다 편리하게 사용할 수 있고, 원하는 기능에 대해 원하는 모듈을 로드할 수 있습니다. 모듈 개발은 특정 규범을 따라야 합니다. 그렇지 않으면 모든 것이 엉망이 될 것입니다.
AMD 사양에 따라 정의를 사용하여 모듈을 정의하고 모듈을 호출하도록 요구할 수 있습니다.
현재 js 모듈 사양에는 CommonJS와 AMD의 두 가지 주요 유형이 있습니다.
AMD는 Asynchronous Module Definition으로, 중국어 이름은 "비동기식 모듈 정의"를 의미합니다. 브라우저 측의 모듈 개발을 위한 사양입니다. 서버 측 사양은 CommonJS
모듈이 비동기적으로 로드되고 모듈 로드가 후속 명령문 실행에 영향을 미치지 않는다는 것입니다. 특정 모듈에 의존하는 모든 명령문은 콜백 함수에 배치됩니다.
AMD는 RequireJS 승격 과정에서 표준화된 모듈 정의 출력입니다.
AMD 사양에서는 전역 변수인 하나의 함수 정의만 정의합니다. 함수 설명:
define(id?, dependencies?, factory);
매개변수 설명:
id:指定义中模块的名字,可选;如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必须是“顶级”的和绝对的(不允许相对名字)。 依赖dependencies:是一个当前模块依赖的,已被模块定义的模块标识的数组字面量。 依赖参数是可选的,如果忽略此参数,它应该默认为["require", "exports", "module"]。然而,如果工厂方法的长度属性小于3,加载器会选择以函数的长度属性指定的参数个数调用工厂方法。 工厂方法factory,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。
모듈 이름은 고유하게 식별하는 데 사용됩니다. 정의에 있는 모듈은 동일합니다. 종속성 배열에서 사용:
模块名是用正斜杠分割的有意义单词的字符串 单词须为驼峰形式,或者".",".." 模块名不允许文件扩展名的形式,如“.js” 模块名可以为 "相对的" 或 "顶级的"。如果首字符为“.”或“..”则为相对的模块名 顶级的模块名从根命名空间的概念模块解析 相对的模块名从 "require" 书写和调用的模块解析
require, 내보내기 및 "라는 이름의 모듈을 사용하여 "alpha"라는 모듈을 만듭니다. beta":
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //Or: return require("beta").verb(); } });
API 소개 필요: //m.sbmmt.com/
AMD 사양 중국어 버전: //m.sbmmt.com/(%E4%B8 %AD%E6 %96%87%E7%89%88)
현재 AMD를 구현하는 라이브러리에는 RequireJS, 컬, 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 객체를 통해 함수를 정의합니다.
모듈 로딩은 파일을 읽고 실행한 후 최종적으로 파일 내부의 module.exports 객체를 반환하는 require 메소드를 사용합니다.
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 사용법: http :/ /m.sbmmt.com/
상상해 보세요. 웹 페이지에 js 파일이 많으면 브라우저는 js 파일을 다운로드할 때 먼저 js 파일을 로드합니다. 파일이 더 있으면 브라우저가 응답하지 않을 수 있습니다. 둘째, js 파일의 종속성을 보장해야 합니다. 종속성이 가장 큰 모듈(파일)을 마지막에 로드해야 합니다. 종속성이 복잡하면 코드 작성 및 유지 관리가 어려워집니다.
RequireJS는 이 두 가지 문제를 해결하기 위해 탄생했습니다:
(1)实现js文件的异步加载,避免网页失去响应; (2)管理模块之间的依赖性,便于代码的编写和维护。
RequireJS 파일 다운로드: //m.sbmmt.com/
CMD(Common Module Definition) 공통 모듈 정의. 이 사양은 모듈의 기본 쓰기 형식과 기본 상호 작용 규칙을 명확히 합니다. 표준은 국내에서 개발되었습니다. AMD는 프런트엔드 종속성이며 CMD는 요청 시 로드됩니다.
CMD 사양에서 모듈은 파일입니다. 코드 작성 형식은 다음과 같습니다.
define(factory);
팩토리가 함수인 경우 모듈의 구성 방법을 의미합니다. 이 생성 메서드를 실행하면 모듈에서 제공하는 인터페이스를 얻을 수 있습니다. 팩토리 메소드가 실행되면 기본적으로 세 가지 매개변수(require, 내보내기 및 모듈)가 전달됩니다.
define(function(require, exports, module) { // 模块代码 });
require는 다른 모듈을 가져올 수 있는 매개변수이며, 내보내기는 모듈의 일부 속성을 메소드와 결합할 수 있습니다. 내보냈습니다.
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)!