我们都知道,虽然我们可以通过原型和继承来使javascript面向对象。但是,当js代码和逻辑过多时,代码的维护和扩展会变的很不方便。这时,nodejs做的非常好,但是在浏览器端模块化的js编程一直都是个难题。而requireJS就是来帮助我们解决这个问题的。requireJS遵循amd规范,所以让我们先了解下关于AMD规范的事情。

一、AMD规范

  AMD规范是浏览器端的模块规范,它的全称为异步模块定义。从名称上看便知它是适合script tag的。也可以说AMD是专门为浏览器中JavaScript环境设计的规范。它吸取了CommonJS的一些优点,但又不照搬它的格式。开始AMD作为CommonJS的transport format 存在,因无法与CommonJS开发者达成一致而独立出来。它有自己的wiki 和讨论组 。

AMD设计出一个简洁的写模块API:

define(id?, dependencies?, factory);

其中:

  • id: 模块标识,可以省略。
  • dependencies: 所依赖的模块,可以省略。
  • factory: 模块的实现,或者一个JavaScript对象。
id遵循CommonJS Module Identifiers 。dependencies元素的顺序和factory参数一一对应。
 
以下是使用AMD模式开发的简单三层结构(基础库/UI层/应用层):
 
base.js
define(function() {
return {
mix: function(source, target) {
}
};
});

  

ui.js

define(['base'], function(base) {
return {
show: function() {
// todo with module base
}
}
});

page.js

define(['base'], function(base) {
    return {
        show: function() {
            // todo with module base
        }
    }
});

data.js

define({
    users: [],
    members: []
});
以上同时演示了define的三种用法
  1. 定义无依赖的模块(base.js)
  2. 定义有依赖的模块(ui.js,page.js)
  3. 定义数据对象模块(data.js)
 
细心的会发现,还有一种没有出现,即具名模块
 
4,具名模块
define('index', ['data','base'], function(data, base) {
    // todo
});
具名模块多数时候是不推荐的,一般由打包工具合并多个模块到一个js文件中时使用。
 
前面提到dependencies元素的顺序和factory一一对应,其实不太严谨。AMD开始为摆脱CommonJS的束缚,开创性的提出了自己的模块风格。但后来又做了妥协,兼容了 CommonJS Modules/Wrappings 。即又可以这样写
 
5,包装模块
define(function(require, exports, module) {
    var base = require('base');
    exports.show = function() {
        // todo with module base
    }
});
不考虑多了一层函数外,格式和Node.js是一样的:使用require获取依赖模块,使用exports导出API。
 
除了define外,AMD还保留一个关键字require。require 作为规范保留的全局标识符,可以实现为 module loader,也可以不实现。
 
目前,实现AMD的库有RequireJS 、curl 、Dojo 、bdLoadJSLocalnet 、Nodules 等。
也有很多库支持AMD规范,即将自己作为一个模块存在,如MooTools 、jQuery 、qwery 、bonzo  甚至还有 firebug 。
二、CMD规范
  与AMD规范类似的还有CMD规范,

在CMD中,一个模块就是一个文件,格式为:
    define( factory );
 
    全局函数define,用来定义模块。
    参数 factory  可以是一个函数,也可以为对象或者字符串。
    当 factory 为对象、字符串时,表示模块的接口就是该对象、字符串。
 
    定义JSON数据模块:
  1. define({ "foo": "bar" });
    通过字符串定义模板模块:

  1. define('this is {{data}}.');
    factory 为函数的时候,表示模块的构造方法,执行构造方法便可以得到模块向外提供的接口。

  1. define( function(require, exports, module) {
  2. // 模块代码
  3. });
    define( id?, deps?, factory );
    define也可以接受两个以上的参数,字符串id为模块标识,数组deps为模块依赖:

  1. define( 'module', ['module1', 'module2'], function( require, exports, module ){
  2. // 模块代码
  3. } );
    其与 AMD 规范用法不同。
 
    require 是 factory 的第一个参数。
    require( id );
    接受模块标识作为唯一的参数,用来获取其他模块提供的接口:

  1. define(function( require, exports ){
  2. var a = require('./a');
  3. a.doSomething();
  4. });
 
    require.async( id, callback? );
    require是同步往下执行的,需要的异步加载模块可以使用 require.async 来进行加载:

  1. define( function(require, exports, module) {
  2. require.async('.a', function(a){
  3. a.doSomething();
  4. });
  5. });
    require.resolve( id )
    可以使用模块内部的路径机制来返回模块路径,不会加载模块。
 
    exports 是 factory 的第二个参数,用来向外提供模块接口。

  1. define(function( require, exports ){
  2. exports.foo = 'bar'; // 向外提供的属性
  3. exports.do = function(){}; // 向外提供的方法
  4. });
    当然也可以使用 return 直接向外提供接口。

  1. define(function( require, exports ){
  2. return{
  3. foo : 'bar', // 向外提供的属性
  4. do : function(){} // 向外提供的方法
  5. }
  6. });
    也可以简化为直接对象字面量的形式:

  1. define({
  2. foo : 'bar', // 向外提供的属性
  3. do : function(){} // 向外提供的方法
  4. });
    与nodeJS中一样需要注意的是,一下方式是错误的:

  1. define(function( require, exports ){
  2. exports = {
  3. foo : 'bar', // 向外提供的属性
  4. do : function(){} // 向外提供的方法
  5. }
  6. });
    需要这么做

  1. define(function( require, exports, module ){
  2. module.exports = {
  3. foo : 'bar', // 向外提供的属性
  4. do : function(){} // 向外提供的方法
  5. }
  6. });
    传入的对象引用可以添加属性,一旦赋值一个新的对象,那么值钱传递进来的对象引用就会失效了。开始之初,exports 是作为 module.exports 的一个引用存在,一切行为只有在这个引用上 factory 才得以正常运行,赋值新的对象后就会断开引用,exports就只是一个新的对象引用,对于factory来说毫无意义,就会出错。
 
    module 是factory的第三个参数,为一个对象,上面存储了一些与当前模块相关联的属性与方法。
        module.id 为模块的唯一标识。
        module.uri 根据模块系统的路径解析规则得到模块的绝对路径。
        module.dependencies 表示模块的依赖。
        module.exports 当前模块对外提供的接口。
   

深入浅出requireJS-1的更多相关文章

  1. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  2. bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

    也许单页程序(Single Page Application)并不是什么时髦的玩意,像Gmail在很早之前就已经在使用这种模式.通常的说法是它通过避免页面刷新大大提高了网站的响应性,像操作桌面应用程序 ...

  3. 实现一个类 RequireJS 的模块加载器 (二)

    2017 新年好 ! 新年第一天对我来说真是悲伤 ,早上兴冲冲地爬起来背着书包跑去实验室,结果今天大家都休息 .回宿舍的时候发现书包湿了,原来盒子装的牛奶盖子松了,泼了一书包,电脑风扇口和USB口都进 ...

  4. 使用RequireJS并实现一个自己的模块加载器 (一)

    RequireJS & SeaJS 在 模块化开发 开发以前,都是直接在页面上引入 script 标签来引用脚本的,当项目变得比较复杂,就会带来很多问题. JS项目中的依赖只有通过引入JS的顺 ...

  5. 使用gulp解决RequireJS项目前端缓存问题(二)

    1.前言 这一节,我们主要解决在上一节<使用gulp解决RequireJSs项目前端缓存问题(一)>末尾提到的几个问题: 对通过require-config.js引入的js文件修改后,没有 ...

  6. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  7. AngularJs2与AMD加载器(dojo requirejs)集成

    现在是西太平洋时间凌晨,这个问题我鼓捣了一天,都没时间学英语了,英语太差,相信第二天我也看不懂了,直接看结果就行. 核心原理就是require在AngularJs2编译过程中是关键字,而在浏览器里面运 ...

  8. 深入浅出Struts2+Spring+Hibernate框架

    一.深入浅出Struts2 什么是Struts2? struts2是一种基于MVC的轻量级的WEB应用框架.有了这个框架我们就可以在这个框架的基础上做起,这样就大大的提高了我们的开发效率和质量,为公司 ...

  9. angularjs集成requirejs

    其实说成使用requirejs加载angularjs应用会更贴切一些 <body> <span ng-controller="homeController"> ...

  10. DOM 事件深入浅出(二)

    在DOM事件深入浅出(一)中,我主要给大家讲解了不同DOM级别下的事件处理程序,同时介绍了事件冒泡和捕获的触发原理和方法.本文将继续介绍DOM事件中的知识点,主要侧重于DOM事件中Event对象的属性 ...

随机推荐

  1. JPA 系列教程 异常 集锦

    异常1.hibernate升级到3.5版本 异常信息摘要: Associations marked as mappedBy must not define database mappings like ...

  2. C#调用托管C++类(DLL)

    毕设是做一个网络摄像头的相关应用.界面用WPF,图像处理部分是OpenCV.没用EmguCV的原因是国内EmguCV的资料相对比较少,EmguCV虽然提供了Winform的控件,在做UI上有一定优势, ...

  3. hadoop 2.2.0 关于map和reduce的个数的设置

    关于hadoop中的map过程,我的理解是每一个map系统会开启一个JVM进程来处理,map之间相互并行,map函数内串行.这样的想法是否正确? 由于想在hadoop集群上算一个初始输入数据不多,但是 ...

  4. CBC之php java兼容版本

    网上搜了N多代码,都是你抄我的,我抄你的,着实让人无语对苍天.经过多番资料的查找,php与java的cbc加密.解密结果终于一致了,代码如下: Java加密解密类: package main; imp ...

  5. Android Monkey 测试策略【转】

    Monkey 测试针对不同的对象和不同的目的,需要采用不同的测试方案. 首先测试的对象.目的及类型如下: 测试的类型 应用程序的稳定性测试 应用程序的压力测试 测试对象 单一 apk apk 集合 测 ...

  6. 获取radio的值

    随着Jquery的作用越来越大,使用的朋友也越来越多.在Web中,由于CheckBox.Radiobutton .DropDownList等控件使用的频率比较高,就关系到这些控件在Jquery中的操作 ...

  7. mysql 取出的日期数据缺少时分秒

    项目使用的数据库是mysql  持久层框架是hibernate  利用SQLQuery 获取日期的时候缺少时分秒   将 .addScalar("dealTS",StandardB ...

  8. HTML通过事件传递参数到js一

    原文链接:http://bbs.51cto.com/thread-1098421-1-1.html 目标处理函数为selectAttr(test) 1.直接传递给定参数如: onclick=" ...

  9. Python之深浅拷贝&函数

    一.深浅拷贝 深浅拷贝是指copy模块下的copy()和deepcopy()方法. 1.浅拷贝 示例: >>> import copy >>> a = 'hello ...

  10. ElasticSearch(3)-原理

    参考文档: http://learnes.net/distributed_crud/bulk_requests.html 一.分布式集群 1.1 空集群 单台机器,其中没有数据,也没有索引. 集群中一 ...