您的位置:首页 > Web前端 > JavaScript

js模块化开发学习

2016-03-11 19:49 579 查看

模块化开发理解

Javascript模块化编程,主要用于实现开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。模块就是实现特定功能的一组方法。有了模块,我们就可以方便的使用别人的代码,需要什么功能,就加载相应的模块。一个模块其实就是一个实现特定功能的文件,这个文件中封装了一些函数和变量。每个模块都提供了对外访问的接口,使得使用者可以方便的调用模块里面封装的方法。有了模块,我们就可以更方便地使用别人的代码,需要什么函数来实现指定功能,就加载相应的模块就可以了。模块开发需要大家按照同样的方式来编写模块,否则就都乱套了。目前,通用的js模块规范有:AMD(
Asynchronous Module Definition
异步模块定义
)、
CMD
(Common Module Definition) 通用模块定义和commonJS。其中AMD和CMD是浏览器端模块化开发的规范,commonJS是服务器端的规范。

AMD规范

该规范通过define方法来定义模块,require方法来调用模块,实现代码的模块加载。模块将被异步加载模块加载不影响后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
AMD
RequireJS
在推广过程中对模块定义的规范化的产出。

RequireJS
学习

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>require</title>
</head>
<body>
<script type="text/javascript" src="js/require.js" data-main="js/main.js"></script>
</body>
</html>
主模块main.js,是整个页面的入口代码
//main.js是主模块,主模块需要依赖其他模块来进行工作
//alert("加载成功");
require(['math','sorts'],function(math,sorts){
console.log(math.add(10,12));
console.log(math.chu(24,12));
console.log([1,5,4,3,2].sort(sorts.compare));
});
其他模块sorts.js
define(function(){
var compare=function(num1,num2){
if(num1<num2){
return -1;
}else if(num1>num2){
return 1;
}else{
return 0;
}
};
return {
compare:compare
};
});
//math.js
define(function(){
var add=function(x,y){
return x+y;
};
var chu=function(x,y){
return x/y;
};
return {
add:add,
chu:chu
};
});
require()函数接受两个参数。第一个参数是一个数组,表示主模块所依赖的模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。主模块的代码就写在回调函数中require()异步加载所需模块,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。

require.config配置

require.config是用来配置模块加载位置,简单点说就是给模块起一个更短更好记的名字,比如将百度的jquery库地址标记为jquery,这样在require时只需要写["jquery"]就可以加载该js,本地的js我们也可以这样配置:
require.config({
paths : {
"jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery"],
"a" : "js/a"
}
})
require(["jquery","a"],function($){
$(function(){
alert("load finished");
})
})
通过paths的配置会使我们的模块名字更精炼,paths还有一个重要的功能,就是可以配置多个路径,如果远程cdn库没有加载成功,可以加载本地的库,如:
require.config({
paths : {
"jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery", "js/jquery"],
"a" : "js/a"
}
})
require(["jquery","a"],function($){
$(function(){
alert("load finished");
})
})
这样配置后,当百度的jquery没有加载成功后,会加载本地js目录下的jquery.在使用requirejs时,加载模块时不用写.js后缀的,当然也是不能写后缀


全局配置

上面的例子中重复出现了require.config配置,如果每个页面中都加入配置,必然显得十分不雅,requirejs提供了一种叫"主数据"的功能,我们首先创建一个main.js:
require.config({
paths : {
"jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery", "js/jquery"],
"a" : "js/a"
}
})
然后再页面中使用下面的方式来使用requirejs:
<script data-main="js/main" src="js/require.js"></script>
加载requirejs脚本的script标签加入了data-main属性,这个属性指定的js将在加载完reuqire.js后处理,我们把require.config的配置加入到data-main后,就可以使每一个页面都使用这个配置,然后页面中就可以直接使用require来加载所有的短模块名data-main还有一个重要的功能,当script标签指定data-main属性时,require会默认的将data-main指定的js为根路径。如上面的data-main="js/main"设定后,我们在使用require(['jquery'])后(不配置jquery的paths),require会自动加载js/jquery.js这个文件,而不是jquery.js。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。

加载非规范的模块

这样的模块在用require()加载之前,要先用require.config()方法,定义它们的一些特征。举例来说,underscore和backbone这两个库,都没有采用AMD规范编写。如果要加载它们的话,必须先定义它们的特征。
require.config({
    shim: {
      'underscore':{
        exports: '_'
      },
      'backbone': {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
      }
    }
  });
require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义(1)exports值(输出的变量名),表明这个模块外部调用时的名称;(2)deps数组,表明该模块的依赖性。jQuery的插件可以这样定义:
shim: {
    'jquery.scroll': {
      deps: ['jquery'],
      exports: 'jQuery.fn.scroll'
    }
  }

require.js插件

domready插件,可以让回调函数在页面DOM结构加载完成后再运行。
require(['domready!'], function (doc){
    // called once the DOM is ready
  });
text和image插件,则是允许require.js加载文本和图片文件。
define([
    'text!review.txt',
    'image!cat.jpg'
    ],

    function(review,cat){
      console.log(review);
      document.body.appendChild(cat);
    }
  );
类似的插件还有json和mdown,用于加载json文件和markdown文件。

CMD规范

CMD
(Common Module Definition) 通用模块定义
。该规范明确了模块的基本书写格式和基本交互规则。该规范是在国内发展出来的。AMD是依赖关系前置,CMD是按需加载。
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD是SeaJS在推广过程中对模块定义的规范化产出
对于依赖的模块,
AMD
是提前执行,
CMD
是延迟执行。
CMD:延迟执行(运行按需加载,根据顺序执行)

AMD:提前执行(异步加载:依赖先执行)+延迟执行

SeaJS
学习

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>seajs</title>
</head>
<body>
<script type="text/javascript" src="sea.js"></script>
<script type="text/javascript">
seajs.use('dialog',function(Dialog){
//alert(Util.add(1,2));
//console.log([1,5,4,3,2].sort(Util.sorts));//[1, 2, 3, 4, 5]
var res=Dialog.sum([1,5,4,3,2]);
console.log(res);//15
});
</script>
</body>
</html>
util,js
define(function(require,exports){
exports.add=function(x,y){
return x+y;
};
exports.sorts=function(num1,num2){
if(num1>num2){
return 1;
}else if(num1<num2){
return -1;
}else{
return 0;
}
};
});
dialog.js
define(function(require,exports){
var util=require('./util.js');
exports.sum=function(arr){
var sum=0;
console.log(arr.sort(util.sorts));
for(var i=0;i<arr.length;i++){
sum+=arr[i];
}
return sum;
};
});
SeaJS对模块的态度是懒执行, 而RequireJS对模块的态度是预执行SeaJS只会在真正需要使用(依赖)模块时才执行该模块SeaJS是异步加载模块的没错, 但执行模块的顺序也是严格按照模块在代码中出现(require)的顺序.而RequireJS会先尽早地执行(依赖)模块, 相当于所有的require都被提前了, 而且模块执行的顺序也不一定100%就是先mod1再mod2因此你看到执行顺序和你预想的完全不一样!

CommonJS规范

CommonJS
是服务器端模块的规范,
Node.js
采用了这个规范。Node.JS首先采用了js模块化的概念。根据
CommonJS
规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为
global
对象的属性。加载模块使用
require
方法,该方法读取一个文件并执行,最后返回文件内部的
module.exports
对象。

待续。。。。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: