zoukankan      html  css  js  c++  java
  • 深入浅出requireJS-1

      我们都知道,虽然我们可以通过原型和继承来使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 当前模块对外提供的接口。
       
  • 相关阅读:
    JavaScript:Number 对象
    JavaScript:Math 对象
    杂项:引用资源列表
    小团队管理与大团队管理
    技术转管理
    【翻译+整理】.NET Core的介绍
    自己开发给自己用的个人知识管理工具【脑细胞】,源码提供
    关于【自证清白】
    这篇博客能让你戒烟——用程序员的思维来戒烟!
    如果我是博客园的产品经理【下】
  • 原文地址:https://www.cnblogs.com/dunken/p/4524093.html
Copyright © 2011-2022 走看看