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对象。
待续。。。。
相关文章推荐
- jstack线程状态分析
- JS---链式调用
- JS---子类调用父类的方法
- 使用JS对HTML标签进行增删改查
- JS堆栈与拷贝
- JavaScript语言基础-环境搭建
- js活动倒计时
- JS中的DOM方法大全
- javascript组件开发
- 【JSOI2014】支线剧情
- 解决json参数中有参数是url地址导致json无法正确传输与解析
- JS 截取字符串substr 和 substring方法的区别
- Javascript进阶篇——(DOM—节点---属性、访问节点)—笔记整理
- Jsp9个内置对象详解
- web session详解
- json转MAp对象
- js事件跨浏览器解决问题的学习与总结
- PJSIP---可以视频通话的库
- JSP总结-会话跟踪全解
- json处理四部曲之第一曲:利用json-lib-xxx.jar处理json