精华内容
下载资源
问答
  • flex 模块化 modules文档

    2009-08-14 13:13:36
    flex 模块化 modules文档,详细介绍如何建立模块化
  • java9 模块化讲解文档

    2018-06-26 09:06:01
    java 9 相关的模块化讲解文档,详细的描述了 模块化的使用方式和具体的技术原理
  • 行业文档-设计装置-笔记本模块化功放器.zip
  • 行业文档-设计装置-模块化通用挂车式装备平台.zip
  • 行业文档-设计装置-模块化设计的数字语音教学系统.zip
  • Abap基础学习文档9_模块化ABAP.doc,非常基础,但非常实用的ABAP学习文档,照着文档练习,肯定就没问题了
  • 主要介绍了Seajs 简易文档 提供简单、极致的模块化开发体验,非官方文档,整理来自己官方文档的文字与实例,方便速查。需要的朋友可以参考下
  • 使用事件指导通过子模块化最大化进行查询偏置的多文档抽象摘要
  • 模块化脚本 Cocos Creator 允许你将代码拆分成多个脚本文件,并且让它们相互调用。要实现这点,你需要了解如何在 Cocos Creator 中定义和使用模块,这个步骤简称为模块化。 如果你还不确定模块化究竟能做什么,...

    模块化脚本

    Cocos Creator 允许你将代码拆分成多个脚本文件,并且让它们相互调用。要实现这点,你需要了解如何在 Cocos Creator 中定义和使用模块,这个步骤简称为模块化

    如果你还不确定模块化究竟能做什么,模块化相当于:

    • C/C++ 中的 include
    • C# 中的 using
    • Java 和 Python 中的 import
    • HTML 中的 <link>

    模块化使你可以在 Cocos Creator 中引用其它脚本文件:

    • 访问其它文件导出的参数
    • 调用其它文件导出的方法
    • 使用其它文件导出的类型
    • 使用或继承其它 Component

    Cocos Creator 中的 JavaScript 使用和 Node.js 几乎相同的 CommonJS 标准来实现模块化,简单来说:

    • 每一个单独的脚本文件就构成一个模块
    • 每个模块都是一个单独的作用域
    • 同步的 require 方法来引用其它模块
    • 设置 module.exports 为导出的变量

    如果你还不太明白,没关系,下面会详细讲解。

    在本文中,“模块”和“脚本”这两个术语是等价的。所有“备注”都属于进阶内容,一开始不需要了解。
    不论模块如何定义,所有用户代码最终会由 Cocos Creator 编译为原生的 JavaScript,可直接在浏览器中运行。

    引用模块

    require

    除了 Cocos Creator 提供的接口,所有用户定义的模块都需要调用 require 来访问。例如我们有一个组件定义在 Rotate.js

    // Rotate.js
    
    cc.Class({
       extends: cc.Component,
       // ...
    });

    现在要在别的脚本里访问它,可以:

    var Rotate = require("Rotate");

    require 返回的就是被模块导出的对象,通常我们都会将结果立即存到一个变量(var Rotate)。传入 require 的字符串就是模块的文件名,这个名字不包含路径也不包含后缀,而且大小写敏感。

    require 完整范例

    接着我们就可以使用 Rotate 派生一个子类,新建一个脚本 SinRotate.js

    // SinRotate.js
    
    var Rotate = require("Rotate");
    
    var SinRotate = cc.Class({
        extends: Rotate,
        update: function (dt) {
            this.rotation += this.speed * Math.sin(dt);
        }
    });

    这里我们定义了一个新的组件叫 SinRotate,它继承自 Rotate,并对 update 方法进行了重写。

    同样的这个组件也可以被其它脚本接着访问,只要用 require("SinRotate")

    备注:

    • require 可以在脚本的任何地方任意时刻进行调用。
    • 游戏开始时会自动 require 所有脚本,这时每个模块内部定义的代码就会被执行一次,所以之后无论又被 require 几次,返回的始终是同一份实例。
    • 调试时,可以随时在 Developer Tools 的 Console 中 require 项目里的任意模块。

    定义模块

    定义组件

    每一个单独的脚本文件就是一个模块,例如前面新建的脚本 Rotate.js

    // Rotate.js
    
    var Rotate = cc.Class({
        extends: cc.Component,
        properties: {
            speed: 1
        },
        update: function () {
            this.transform.rotation += this.speed;
        }
    });

    当你在脚本中声明了一个组件,Cocos Creator 会默认把它导出,其它脚本直接 require 这个模块就能使用这个组件。

    定义普通 JavaScript 模块

    模块里不单单能定义组件,实际上你可以导出任意 JavaScript 对象。假设有个脚本 config.js

    // config.js
    
    var cfg = {
        moveSpeed: 10,
        version: "0.15",
        showTutorial: true,
    
        load: function () {
            // ...
        }
    };
    cfg.load();

    现在如果我们要在其它脚本中访问 config 对象:

    // player.js
    
    var config = require("config");
    cc.log("speed is", config.moveSpeed);

    结果会有报错:"TypeError: Cannot read property 'moveSpeed' of null",这是因为 cfg 没有被导出。由于 require 实际上获取的是目标脚本内的 module.exports 变量,所以我们还需要在 config.js 的最后设置 module.exports = config

    // config.js - v2
    
    var cfg = {
        moveSpeed: 10,
        version: "0.15",
        showTutorial: true,
    
        load: function () {
            // ...
        }
    };
    cfg.load();
    
    module.exports = cfg;

    这样 player.js 便能正确输出:"speed is 10"。

    那为什么定义 Component 时可以不用设置 exports ? 因为 Component 是 Cocos Creator 中的特殊类型,如果一个脚本定义了 Component 却没有声明 exports,Cocos Creator 会自动将 exports 设置为 Component。

    备注:

    • 在 module 上增加的其它变量是不能导出的,也就是说 exports 不能替换成其它变量名,系统只会读取 exports 这个变量。

    更多示例

    导出变量

    • module.exports 默认是一个空对象({}),可以直接往里面增加新的字段。
    // foobar.js:
    
    module.exports.foo = function () {
        cc.log("foo");
    };
    module.exports.bar = function () {
        cc.log("bar");
    };
    // test.js:
    
    var foobar = require("foobar");
    foobar.foo();    // "foo"
    foobar.bar();    // "bar"
    • module.exports 的值可以是任意 JavaScript 类型。
    // foobar.js:
    
    module.exports = {
        FOO: function () {
            this.type = "foo";
        },
        bar: "bar"
    };
    // test.js:
    
    var foobar = require("foobar");
    var foo = new foobar.FOO();
    cc.log(foo.type);      // "foo"
    cc.log(foobar.bar);    // "bar"

    封装私有变量

    每个脚本都是一个单独的作用域,在脚本内使用 var 定义的局部变量,将无法被模块外部访问。我们可以很轻松的封装模块内的私有变量:

    // foobar.js:
    
    var dirty = false;
    module.exports = {
        setDirty: function () {
            dirty = true;
        },
        isDirty: function () {
            return dirty;
        },
    };
    // test1.js:
    
    var foo = require("foobar");
    cc.log(typeof foo.dirty);        // "undefined"
    foo.setDirty();
    // test2.js:
    
    var foo = require("foobar");
    cc.log(foo.isDirty());           // true

    循环引用

    请参考属性延迟定义

    第三方模块引用

    请参考第三方模块引用文档

    展开全文
  • js模块文档下载

    2017-11-27 13:38:32
    js模块化 js模块化 js模块化 js模块化 js模块化 js模块化
  • Cocos Creator 允许你将代码拆分成多个...如果你还不确定模块化究竟能做什么,模块化相当于:C/C++ 中的 includeC# 中的 usingJava 和 Python 中的 importHTML 中的 模块化使你可以在 Cocos Creator 中引用其它脚

    Cocos Creator 允许你将代码拆分成多个脚本文件,并且让它们相互调用。要实现这点,你需要了解如何在 Cocos Creator 中定义和使用模块,这个步骤简称为模块化

    如果你还不确定模块化究竟能做什么,模块化相当于:

    • C/C++ 中的 include
    • C# 中的 using
    • Java 和 Python 中的 import
    • HTML 中的 <link>

    模块化使你可以在 Cocos Creator 中引用其它脚本文件:

    • 访问其它文件导出的参数
    • 调用其它文件导出的方法
    • 使用其它文件导出的类型
    • 使用或继承其它 Component

    Cocos Creator 中的 JavaScript 使用和 Node.js 几乎相同的 CommonJS 标准来实现模块化,简单来说:

    • 每一个单独的脚本文件就构成一个模块
    • 每个模块都是一个单独的作用域
    • 同步的 require 方法来引用其它模块
    • 设置 module.exports 为导出的变量

    如果你还不太明白,没关系,下面会详细讲解。

    在本文中,“模块”和“脚本”这两个术语是等价的。所有“备注”都属于进阶内容,一开始不需要了解。
    不论模块如何定义,所有用户代码最终会由 Cocos Creator 编译为原生的 JavaScript,可直接在浏览器中运行。

    引用模块

    require

    除了 Cocos Creator 提供的接口,所有用户定义的模块都需要调用 require 来访问。例如我们有一个组件定义在 Rotate.js

    // Rotate.js
    
    cc.Class({
       extends: cc.Component,
       // ...
    });

    现在要在别的脚本里访问它,可以:

    var Rotate = require("Rotate");

    require 返回的就是被模块导出的对象,通常我们都会将结果立即存到一个变量(var Rotate)。传入 require的字符串就是模块的文件名,这个名字不包含路径也不包含后缀,而且大小写敏感。

    require 完整范例

    接着我们就可以使用 Rotate 派生一个子类,新建一个脚本 SinRotate.js

    // SinRotate.js
    
    var Rotate = require("Rotate");
    
    var SinRotate = cc.Class({
        extends: Rotate,
        update: function (dt) {
            this.rotation += this.speed * Math.sin(dt);
        }
    });

    这里我们定义了一个新的组件叫 SinRotate,它继承自 Rotate,并对 update 方法进行了重写。

    同样的这个组件也可以被其它脚本接着访问,只要用 require("SinRotate")

    备注:

    • require 可以在脚本的任何地方任意时刻进行调用。
    • 游戏开始时会自动 require 所有脚本,这时每个模块内部定义的代码就会被执行一次,所以之后无论又被 require 几次,返回的始终是同一份实例。
    • 调试时,可以随时在 Developer Tools 的 Console 中 require 项目里的任意模块

    定义模块

    定义组件

    每一个单独的脚本文件就是一个模块,例如前面新建的脚本 Rotate.js

    // Rotate.js
    
    var Rotate = cc.Class({
        extends: cc.Component,
        properties: {
            speed: 1
        },
        update: function () {
            this.transform.rotation += this.speed;
        }
    });

    当你在脚本中声明了一个组件,Cocos Creator 会默认把它导出,其它脚本直接 require 这个模块就能使用这个组件。

    定义普通 JavaScript 模块

    模块里不单单能定义组件,实际上你可以导出任意 JavaScript 对象。假设有个脚本 config.js

    // config.js
    
    var cfg = {
        moveSpeed: 10,
        version: "0.15",
        showTutorial: true,
    
        load: function () {
            // ...
        }
    };
    cfg.load();

    现在如果我们要在其它脚本中访问 config 对象:

    // player.js
    
    var config = require("config");
    cc.log("speed is", config.moveSpeed);

    结果会有报错:"TypeError: Cannot read property 'moveSpeed' of null",这是因为 cfg 没有被导出。由于 require 实际上获取的是目标脚本内的 module.exports 变量,所以我们还需要在 config.js 的最后设置 module.exports = config

    // config.js - v2
    
    var cfg = {
        moveSpeed: 10,
        version: "0.15",
        showTutorial: true,
    
        load: function () {
            // ...
        }
    };
    cfg.load();
    
    module.exports = cfg;

    这样 player.js 便能正确输出:"speed is 10"。

    那为什么定义 Component 时可以不用设置 exports ? 因为 Component 是 Cocos Creator 中的特殊类型,如果一个脚本定义了 Component 却没有声明 exports,Cocos Creator 会自动将 exports 设置为 Component。

    备注:

    • 在 module 上增加的其它变量是不能导出的,也就是说 exports 不能替换成其它变量名,系统只会读取 exports 这个变量。

    更多示例

    导出变量

    • module.exports 默认是一个空对象({}),可以直接往里面增加新的字段。
    // foobar.js:
    
    module.exports.foo = function () {
        cc.log("foo");
    };
    module.exports.bar = function () {
        cc.log("bar");
    };
    // test.js:
    
    var foobar = require("foobar");
    foobar.foo();    // "foo"
    foobar.bar();    // "bar"
    • module.exports 的值可以是任意 JavaScript 类型。
    // foobar.js:
    
    module.exports = {
        FOO: function () {
            this.type = "foo";
        },
        bar: "bar"
    };
    // test.js:
    
    var foobar = require("foobar");
    var foo = new foobar.FOO();
    cc.log(foo.type);      // "foo"
    cc.log(foobar.bar);    // "bar"

    封装私有变量

    每个脚本都是一个单独的作用域,在脚本内使用 var 定义的局部变量,将无法被模块外部访问。我们可以很轻松的封装模块内的私有变量

    // foobar.js:
    
    var dirty = false;
    module.exports = {
        setDirty: function () {
            dirty = true;
        },
        isDirty: function () {
            return dirty;
        },
    };
    // test1.js:
    
    var foo = require("foobar");
    cc.log(typeof foo.dirty);        // "undefined"
    foo.setDirty();
    // test2.js:
    
    var foo = require("foobar");
    cc.log(foo.isDirty());           // true

    循环引用

    请参考属性延迟定义

    第三方模块引用

    请参考第三方模块引用文档

    展开全文
  • 系统功能模块设计文档,系统模块化管理的参考文档,将系统以模块化分,列出各个模块的功能列表
  • 两个软件详细设计说明文档模块,大家自己远吧。
  • 模块化的js.pdf

    2013-09-23 11:24:23
    模块化的js . pdf pdf文档 介绍模块化的js
  • 前端模块化详解(完整版)

    万次阅读 多人点赞 2019-02-16 19:13:46
    前言 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很...本文内容主要有理解模块化,为什么要模块化模块化的优缺点以及模块化规范,并且介绍下开发中...

    前言

    在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀,此时在JS方面就会考虑使用模块化规范去管理。
    本文内容主要有理解模块化,为什么要模块化,模块化的优缺点以及模块化规范,并且介绍下开发中最流行的CommonJS, AMD, ES6、CMD规范。本文试图站在小白的角度,用通俗易懂的笔调介绍这些枯燥无味的概念,希望诸君阅读后,对模块化编程有个全新的认识和理解!

    建议下载本文源代码,自己动手敲一遍,请猛戳GitHub个人博客(全集)

    模块化规范

    一、模块化的理解

    1.什么是模块?

    • 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
    • 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信

    2.模块化的进化过程

    • 全局function模式 : 将不同的功能封装成不同的全局函数
      • 编码: 将不同的功能封装成不同的全局函数
      • 问题: 污染全局命名空间, 容易引起命名冲突或数据不安全,而且模块成员之间看不出直接关系
    function m1(){
      //...
    }
    function m2(){
      //...
    }
    
    • namespace模式 : 简单对象封装
      • 作用: 减少了全局变量,解决命名冲突
      • 问题: 数据不安全(外部可以直接修改模块内部的数据)
    let myModule = {
      data: 'www.baidu.com',
      foo() {
        console.log(`foo() ${this.data}`)
      },
      bar() {
        console.log(`bar() ${this.data}`)
      }
    }
    myModule.data = 'other data' //能直接修改模块内部的数据
    myModule.foo() // foo() other data
    

    这样的写法会暴露所有模块成员,内部状态可以被外部改写。

    • IIFE模式:匿名函数自调用(闭包)
      • 作用: 数据是私有的, 外部只能通过暴露的方法操作
      • 编码: 将数据和行为封装到一个函数内部, 通过给window添加属性来向外暴露接口
      • 问题: 如果当前这个模块依赖另一个模块怎么办?
    // index.html文件
    <script type="text/javascript" src="module.js"></script>
    <script type="text/javascript">
        myModule.foo()
        myModule.bar()
        console.log(myModule.data) //undefined 不能访问模块内部数据
        myModule.data = 'xxxx' //不是修改的模块内部的data
        myModule.foo() //没有改变
    </script>
    
    // module.js文件
    (function(window) {
      let data = 'www.baidu.com'
      //操作数据的函数
      function foo() {
        //用于暴露有函数
        console.log(`foo() ${data}`)
      }
      function bar() {
        //用于暴露有函数
        console.log(`bar() ${data}`)
        otherFun() //内部调用
      }
      function otherFun() {
        //内部私有的函数
        console.log('otherFun()')
      }
      //暴露行为
      window.myModule = { foo, bar } //ES6写法
    })(window)
    

    最后得到的结果:

    • IIFE模式增强 : 引入依赖

    这就是现代模块实现的基石

    // module.js文件
    (function(window, $) {
      let data = 'www.baidu.com'
      //操作数据的函数
      function foo() {
        //用于暴露有函数
        console.log(`foo() ${data}`)
        $('body').css('background', 'red')
      }
      function bar() {
        //用于暴露有函数
        console.log(`bar() ${data}`)
        otherFun() //内部调用
      }
      function otherFun() {
        //内部私有的函数
        console.log('otherFun()')
      }
      //暴露行为
      window.myModule = { foo, bar }
    })(window, jQuery)
    
     // index.html文件
      <!-- 引入的js必须有一定顺序 -->
      <script type="text/javascript" src="jquery-1.10.1.js"></script>
      <script type="text/javascript" src="module.js"></script>
      <script type="text/javascript">
        myModule.foo()
      </script>
    

    上例子通过jquery方法将页面的背景颜色改成红色,所以必须先引入jQuery库,就把这个库当作参数传入。这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显

    3. 模块化的好处

    • 避免命名冲突(减少命名空间污染)
    • 更好的分离, 按需加载
    • 更高复用性
    • 高可维护性

    4. 引入多个<script>后出现出现问题

    • 请求过多

    首先我们要依赖多个模块,那样就会发送多个请求,导致请求过多

    • 依赖模糊

    我们不知道他们的具体依赖关系是什么,也就是说很容易因为不了解他们之间的依赖关系导致加载先后顺序出错。

    • 难以维护

    以上两种原因就导致了很难维护,很可能出现牵一发而动全身的情况导致项目出现严重的问题。
    模块化固然有多个好处,然而一个页面需要引入多个js文件,就会出现以上这些问题。而这些问题可以通过模块化规范来解决,下面介绍开发中最流行的commonjs, AMD, ES6, CMD规范。

    二、模块化规范

    1.CommonJS

    (1)概述

    Node 应用由模块组成,采用 CommonJS 模块规范。每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。在服务器端,模块的加载是运行时同步加载的;在浏览器端,模块需要提前编译打包处理。

    (2)特点

    • 所有代码都运行在模块作用域,不会污染全局作用域。
    • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
    • 模块加载的顺序,按照其在代码中出现的顺序。

    (3)基本语法

    • 暴露模块:module.exports = valueexports.xxx = value
    • 引入模块:require(xxx),如果是第三方模块,xxx为模块名;如果是自定义模块,xxx为模块文件路径

    此处我们有个疑问:CommonJS暴露的模块到底是什么? CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性

    // example.js
    var x = 5;
    var addX = function (value) {
      return value + x;
    };
    module.exports.x = x;
    module.exports.addX = addX;
    

    上面代码通过module.exports输出变量x和函数addX。

    var example = require('./example.js');//如果参数字符串以“./”开头,则表示加载的是一个位于相对路径
    console.log(example.x); // 5
    console.log(example.addX(1)); // 6
    

    require命令用于加载模块文件。require命令的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的exports对象。如果没有发现指定模块,会报错

    (4)模块的加载机制

    CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。这点与ES6模块化有重大差异(下文会介绍),请看下面这个例子:

    // lib.js
    var counter = 3;
    function incCounter() {
      counter++;
    }
    module.exports = {
      counter: counter,
      incCounter: incCounter,
    };
    
    

    上面代码输出内部变量counter和改写这个变量的内部方法incCounter。

    // main.js
    var counter = require('./lib').counter;
    var incCounter = require('./lib').incCounter;
    
    console.log(counter);  // 3
    incCounter();
    console.log(counter); // 3
    

    上面代码说明,counter输出以后,lib.js模块内部的变化就影响不到counter了。这是因为counter是一个原始类型的值,会被缓存。除非写成一个函数,才能得到内部变动后的值

    (5)服务器端实现

    ①下载安装node.js

    ②创建项目结构

    注意:用npm init 自动生成package.json时,package name(包名)不能有中文和大写

    |-modules
      |-module1.js
      |-module2.js
      |-module3.js
    |-app.js
    |-package.json
      {
        "name": "commonJS-node",
        "version": "1.0.0"
      }
    

    ③下载第三方模块

    npm install uniq --save // 用于数组去重

    ④定义模块代码

    //module1.js
    module.exports = {
      msg: 'module1',
      foo() {
        console.log(this.msg)
      }
    }
    
    //module2.js
    module.exports = function() {
      console.log('module2')
    }
    
    //module3.js
    exports.foo = function() {
      console.log('foo() module3')
    }
    exports.arr = [1, 2, 3, 3, 2]
    
    // app.js文件
    // 引入第三方库,应该放置在最前面
    let uniq = require('uniq')
    let module1 = require('./modules/module1')
    let module2 = require('./modules/module2')
    let module3 = require('./modules/module3')
    
    module1.foo() //module1
    module2() //module2
    module3.foo() //foo() module3
    console.log(uniq(module3.arr)) //[ 1, 2, 3 ]
    

    ⑤通过node运行app.js

    命令行输入node app.js,运行JS文件

    (6)浏览器端实现(借助Browserify)

    ①创建项目结构

    |-js
      |-dist //打包生成文件的目录
      |-src //源码所在的目录
        |-module1.js
        |-module2.js
        |-module3.js
        |-app.js //应用主源文件
    |-index.html //运行于浏览器上
    |-package.json
      {
        "name": "browserify-test",
        "version": "1.0.0"
      }
    

    ②下载browserify

    • 全局: npm install browserify -g
    • 局部: npm install browserify --save-dev

    ③定义模块代码(同服务器端)

    注意:index.html文件要运行在浏览器上,需要借助browserify将app.js文件打包编译,如果直接在index.html引入app.js就会报错!

    ④打包处理js

    根目录下运行browserify js/src/app.js -o js/dist/bundle.js

    ⑤页面使用引入

    在index.html文件中引入<script type="text/javascript" src="js/dist/bundle.js"></script>

    2.AMD

    CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是非同步加载模块,允许指定回调函数。由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。此外AMD规范比CommonJS规范在浏览器端实现要来着早。

    (1)AMD规范基本语法

    定义暴露模块:

    //定义没有依赖的模块
    define(function(){
       return 模块
    })
    
    //定义有依赖的模块
    define(['module1', 'module2'], function(m1, m2){
       return 模块
    })
    

    引入使用模块:

    require(['module1', 'module2'], function(m1, m2){
       使用m1/m2
    })
    

    (2)未使用AMD规范与使用require.js

    通过比较两者的实现方法,来说明使用AMD规范的好处。

    • 未使用AMD规范
    // dataService.js文件
    (function (window) {
      let msg = 'www.baidu.com'
      function getMsg() {
        return msg.toUpperCase()
      }
      window.dataService = {getMsg}
    })(window)
    
    // alerter.js文件
    (function (window, dataService) {
      let name = 'Tom'
      function showMsg() {
        alert(dataService.getMsg() + ', ' + name)
      }
      window.alerter = {showMsg}
    })(window, dataService)
    
    // main.js文件
    (function (alerter) {
      alerter.showMsg()
    })(alerter)
    
    // index.html文件
    <div><h1>Modular Demo 1: 未使用AMD(require.js)</h1></div>
    <script type="text/javascript" src="js/modules/dataService.js"></script>
    <script type="text/javascript" src="js/modules/alerter.js"></script>
    <script type="text/javascript" src="js/main.js"></script>
    

    最后得到如下结果:

    这种方式缺点很明显:首先会发送多个请求,其次引入的js文件顺序不能搞错,否则会报错!

    • 使用require.js

    RequireJS是一个工具库,主要用于客户端的模块管理。它的模块管理遵守AMD规范,RequireJS的基本思想是,通过define方法,将代码定义为模块;通过require方法,实现代码的模块加载
    接下来介绍AMD规范在浏览器实现的步骤:

    ①下载require.js, 并引入

    • 官网: http://www.requirejs.cn/
    • github : https://github.com/requirejs/requirejs

    然后将require.js导入项目: js/libs/require.js

    ②创建项目结构

    |-js
      |-libs
        |-require.js
      |-modules
        |-alerter.js
        |-dataService.js
      |-main.js
    |-index.html
    

    ③定义require.js的模块代码

    // dataService.js文件
    // 定义没有依赖的模块
    define(function() {
      let msg = 'www.baidu.com'
      function getMsg() {
        return msg.toUpperCase()
      }
      return { getMsg } // 暴露模块
    })
    
    //alerter.js文件
    // 定义有依赖的模块
    define(['dataService'], function(dataService) {
      let name = 'Tom'
      function showMsg() {
        alert(dataService.getMsg() + ', ' + name)
      }
      // 暴露模块
      return { showMsg }
    })
    
    // main.js文件
    (function() {
      require.config({
        baseUrl: 'js/', //基本路径 出发点在根目录下
        paths: {
          //映射: 模块标识名: 路径
          alerter: './modules/alerter', //此处不能写成alerter.js,会报错
          dataService: './modules/dataService'
        }
      })
      require(['alerter'], function(alerter) {
        alerter.showMsg()
      })
    })()
    
    // index.html文件
    <!DOCTYPE html>
    <html>
      <head>
        <title>Modular Demo</title>
      </head>
      <body>
        <!-- 引入require.js并指定js主文件的入口 -->
        <script data-main="js/main" src="js/libs/require.js"></script>
      </body>
    </html>
    

    ④页面引入require.js模块:

    在index.html引入 <script data-main="js/main" src="js/libs/require.js"></script>

    此外在项目中如何引入第三方库?只需在上面代码的基础稍作修改:

    // alerter.js文件
    define(['dataService', 'jquery'], function(dataService, $) {
      let name = 'Tom'
      function showMsg() {
        alert(dataService.getMsg() + ', ' + name)
      }
      $('body').css('background', 'green')
      // 暴露模块
      return { showMsg }
    })
    
    // main.js文件
    (function() {
      require.config({
        baseUrl: 'js/', //基本路径 出发点在根目录下
        paths: {
          //自定义模块
          alerter: './modules/alerter', //此处不能写成alerter.js,会报错
          dataService: './modules/dataService',
          // 第三方库模块
          jquery: './libs/jquery-1.10.1' //注意:写成jQuery会报错
        }
      })
      require(['alerter'], function(alerter) {
        alerter.showMsg()
      })
    })()
    

    上例是在alerter.js文件中引入jQuery第三方库,main.js文件也要有相应的路径配置。
    小结:通过两者的比较,可以得出AMD模块定义的方法非常清晰,不会污染全局环境,能够清楚地显示依赖关系。AMD模式可以用于浏览器环境,并且允许非同步加载模块,也可以根据需要动态加载模块。

    3.CMD

    CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。CMD规范整合了CommonJS和AMD规范的特点。在 Sea.js 中,所有 JavaScript 模块都遵循 CMD模块定义规范。

    (1)CMD规范基本语法

    定义暴露模块:

    //定义没有依赖的模块
    define(function(require, exports, module){
      exports.xxx = value
      module.exports = value
    })
    
    //定义有依赖的模块
    define(function(require, exports, module){
      //引入依赖模块(同步)
      var module2 = require('./module2')
      //引入依赖模块(异步)
        require.async('./module3', function (m3) {
        })
      //暴露模块
      exports.xxx = value
    })
    

    引入使用模块:

    define(function (require) {
      var m1 = require('./module1')
      var m4 = require('./module4')
      m1.show()
      m4.show()
    })
    

    (2)sea.js简单使用教程

    ①下载sea.js, 并引入

    然后将sea.js导入项目: js/libs/sea.js

    ②创建项目结构

    |-js
      |-libs
        |-sea.js
      |-modules
        |-module1.js
        |-module2.js
        |-module3.js
        |-module4.js
        |-main.js
    |-index.html
    

    ③定义sea.js的模块代码

    // module1.js文件
    define(function (require, exports, module) {
      //内部变量数据
      var data = 'atguigu.com'
      //内部函数
      function show() {
        console.log('module1 show() ' + data)
      }
      //向外暴露
      exports.show = show
    })
    
    // module2.js文件
    define(function (require, exports, module) {
      module.exports = {
        msg: 'I Will Back'
      }
    })
    
    // module3.js文件
    define(function(require, exports, module) {
      const API_KEY = 'abc123'
      exports.API_KEY = API_KEY
    })
    
    // module4.js文件
    define(function (require, exports, module) {
      //引入依赖模块(同步)
      var module2 = require('./module2')
      function show() {
        console.log('module4 show() ' + module2.msg)
      }
      exports.show = show
      //引入依赖模块(异步)
      require.async('./module3', function (m3) {
        console.log('异步引入依赖模块3  ' + m3.API_KEY)
      })
    })
    
    // main.js文件
    define(function (require) {
      var m1 = require('./module1')
      var m4 = require('./module4')
      m1.show()
      m4.show()
    })
    

    ④在index.html中引入

    <script type="text/javascript" src="js/libs/sea.js"></script>
    <script type="text/javascript">
      seajs.use('./js/modules/main')
    </script>
    

    最后得到结果如下:

    4.ES6模块化

    ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。

    (1)ES6模块化语法

    export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

    /** 定义模块 math.js **/
    var basicNum = 0;
    var add = function (a, b) {
        return a + b;
    };
    export { basicNum, add };
    /** 引用模块 **/
    import { basicNum, add } from './math';
    function test(ele) {
        ele.textContent = add(99 + basicNum);
    }
    

    如上例所示,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

    // export-default.js
    export default function () {
      console.log('foo');
    }
    
    // import-default.js
    import customName from './export-default';
    customName(); // 'foo'
    

    模块默认输出, 其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

    (2)ES6 模块与 CommonJS 模块的差异

    它们有两个重大差异:

    ① CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用

    ② CommonJS 模块是运行时加载,ES6 模块是编译时输出接口

    第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

    下面重点解释第一个差异,我们还是举上面那个CommonJS模块的加载机制例子:

    // lib.js
    export let counter = 3;
    export function incCounter() {
      counter++;
    }
    // main.js
    import { counter, incCounter } from './lib';
    console.log(counter); // 3
    incCounter();
    console.log(counter); // 4
    

    ES6 模块的运行机制与 CommonJS 不一样。ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块

    (3) ES6-Babel-Browserify使用教程

    简单来说就一句话:使用Babel将ES6编译为ES5代码,使用Browserify编译打包js

    ①定义package.json文件

     {
       "name" : "es6-babel-browserify",
       "version" : "1.0.0"
     }
    

    ②安装babel-cli, babel-preset-es2015和browserify

    • npm install babel-cli browserify -g
    • npm install babel-preset-es2015 --save-dev
    • preset 预设(将es6转换成es5的所有插件打包)

    ③定义.babelrc文件

      {
        "presets": ["es2015"]
      }
    

    ④定义模块代码

    //module1.js文件
    // 分别暴露
    export function foo() {
      console.log('foo() module1')
    }
    export function bar() {
      console.log('bar() module1')
    }
    
    //module2.js文件
    // 统一暴露
    function fun1() {
      console.log('fun1() module2')
    }
    function fun2() {
      console.log('fun2() module2')
    }
    export { fun1, fun2 }
    
    //module3.js文件
    // 默认暴露 可以暴露任意数据类项,暴露什么数据,接收到就是什么数据
    export default () => {
      console.log('默认暴露')
    }
    
    // app.js文件
    import { foo, bar } from './module1'
    import { fun1, fun2 } from './module2'
    import module3 from './module3'
    foo()
    bar()
    fun1()
    fun2()
    module3()
    

    ⑤ 编译并在index.html中引入

    • 使用Babel将ES6编译为ES5代码(但包含CommonJS语法) : babel js/src -d js/lib
    • 使用Browserify编译js : browserify js/lib/app.js -o js/lib/bundle.js

    然后在index.html文件中引入

     <script type="text/javascript" src="js/lib/bundle.js"></script>
    

    最后得到如下结果:

    此外第三方库(以jQuery为例)如何引入呢
    首先安装依赖npm install jquery@1
    然后在app.js文件中引入

    //app.js文件
    import { foo, bar } from './module1'
    import { fun1, fun2 } from './module2'
    import module3 from './module3'
    import $ from 'jquery'
    
    foo()
    bar()
    fun1()
    fun2()
    module3()
    $('body').css('background', 'green')
    

    三、总结

    • CommonJS规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。
    • AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。
    • CMD规范与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重
    • ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案

    参考文章

    前端模块化开发那点历史

    CommonJS,AMD,CMD区别

    AMD 和 CMD 的区别有哪些?

    Javascript模块化编程

    Javascript标准参考教程

    CMD 模块定义规范

    理解CommonJS、AMD、CMD三种规范

    展开全文
  • Servlet3.0模块化支持

    千次阅读 2017-06-27 12:29:39
    le示例支持Servlet3.0模块化支持 Servlet3.0现在已经支持各Web组件的模块化了。也就是说现在我们可以把各Web组件单独拿出来进行开发,之后把它们打成对应的jar包放到主项目中就可以了,而不必像之前那样——所有的...
    
    

    Servlet3.0模块化支持

     

           Servlet3.0现在已经支持各Web组件的模块化了。也就是说现在我们可以把各Web组件单独拿出来进行开发,之后把它们打成对应的jar包放到主项目中就可以了,而不必像之前那样——所有的内容都必须在web.xml文件中进行定义。有了对模块化的支持后我们在实际应用中就可以把某些通用功能的Filter、Listener、Servlet作为一个单独的Web模块进行定义,在需要使用它们的项目中就把对应Web模块对应的jar包加进去就可以了。是不是很有用呢?接下来我们就来看一下这些Web组件究竟是怎样模块化的。

           Web模块打成的jar包的内容的文件结构要求是这个样子的:

    |--META-INF

    |     |--web-fragment.xml

    |     |--resources

    |     |     |--jsp、图片等,相当于web的根目录

    |--class文件和类路径下的文件

     

           其中web-fragment.xml文件是必须要的。上述目录结构就相当于在我们的类路径下有一个META-INF目录,该目录下有web-fragment.xml文件及包含jsp、图片等资源的resources目录。针对于上述这样的目录结构,所以当我们在使用Maven构建项目的时候,我们的Maven项目的目录结构应该是这个样子的:



     
           web-fragment.xml文件的作用与Web应用下的web.xml文件的作用是相似的,在web.xml文件可以配置的信息都可以在web-fragment.xml文件中进行配置。此外,它们的文档结构也非常的相似。所不同的是web-fragment.xml文件的根元素是web-fragment,所使用的schema也是web-fragment相应的schema。

    Xml代码   收藏代码
    1. <web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"  
    2.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    3.    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd">  
    4.     
    5. </web-fragment>  

     

           另外,在web-fragment.xml文件中我们可以通过<name>元素来指定当前模块的名称,用<ordering>元素来指定当前模块相对的加载顺序。<ordering>元素下面可以指定<before>或<after>元素,而<before>和<after>元素下又可以指定<name>和<others>元素。我们来看几个指定ordering的示例。

    在其他模块之前加载

    Xml代码   收藏代码
    1. <ordering>  
    2.    <!-- 在其它模块之前加载 -->  
    3.    <before>  
    4.       <others/>  
    5.    </before>  
    6. </ordering>  

      

    在指定模块之后加载

    Xml代码   收藏代码
    1. <ordering>  
    2.    <!-- 在指定模块之后加载 -->  
    3.    <after>  
    4.       <name>模块名称</name>  
    5.    </after>  
    6. </ordering>  

      

           除了可以在web-fragment.xml文件里面通过<ordering>元素定义当前模块的加载顺序外,我们还可以在web.xml文件中通过<absolute-ordering>元素指定各模块的 加载顺序。而且web.xml文件中指定的加载顺序比web-fragment.xml文件中指定的加载顺序具有更高的优先级。如:

    Xml代码   收藏代码
    1. <absolute-ordering>  
    2.    <name>module1</name>  
    3.    <name>module2</name>  
    4.    <name>module3</name>  
    5.    <others/>  
    6. </absolute-ordering>  

      

           接下来我们来展示一个创建web模块的例子。假设我们要创建一个叫做module1的模块,其中含有一个Module1Servlet,其代码如下所示:

    Java代码   收藏代码
    1. public class Module1Servlet extends HttpServlet {  
    2.    
    3.    private static final long serialVersionUID = 1L;  
    4.    
    5.    @Override  
    6.    protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
    7.          throws ServletException, IOException {  
    8.       this.doPost(req, resp);  
    9.    }  
    10.    
    11.    @Override  
    12.    protected void doPost(HttpServletRequest req, HttpServletResponse resp)  
    13.          throws ServletException, IOException {  
    14.       req.getRequestDispatcher("/module1.jsp").forward(req, resp);  
    15.    }  
    16.    
    17. }  

      

           接着我们在类路径下创建一个META-INF文件夹,在该文件夹下创建一个resources目录,在resources目录下创建一个module1.jsp文件。接着在META-INF目录下创建一个web-fragment.xml文件,其内容如下:

    Xml代码   收藏代码
    1. <web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"  
    2.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    3.    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd">  
    4.     
    5.    <!-- 指定模块名称 -->  
    6.    <name>module1</name>  
    7.    <!-- 加载顺序 -->  
    8.    <ordering>  
    9.       <!-- 在其它模块之前加载 -->  
    10.       <before>  
    11.          <others/>  
    12.       </before>  
    13.    </ordering>  
    14.     
    15.    <servlet>  
    16.       <servlet-name>module1Servlet</servlet-name>  
    17.       <servlet-class>com.xxx.Module1Servlet</servlet-class>  
    18.    </servlet>  
    19.     
    20.    <servlet-mapping>  
    21.       <servlet-name>module1Servlet</servlet-name>  
    22.       <url-pattern>/servlet/module1</url-pattern>  
    23.    </servlet-mapping>  
    24.     
    25. </web-fragment>  

     

           之后我们把该项目打成一个jar包就可以把它作为一个jar加到其它Web应用中,在其它Web应用中使用了。放到其它Web应用中后,我们通过访问/servlet/module1就可以访问到我们module1模块中定义的Module1Servlet了。

    展开全文
  • 模块化开发

    千次阅读 2015-03-30 22:23:57
    什么是模块化模块化是个一般概念,这一概念也适用于软件开发,可以让软件按模块单独开发,各模块通常都用一个标准化的接口来进行通信。实际上,除了规模大小有区别外,面向对象语言中对象之间的关注点分离与模块...
  • Python模块化编程

    千次阅读 多人点赞 2018-11-01 16:59:11
    模块化 自定义模块 模块的内置属性 导入模块 安装第三方模块 查看模块的属性和方法 模块化 在Python中,一个.py文件就称之为一个模块(Module),为了避免模块名冲突,Python又引入了按目录来组织模块的方法,...
  • 写这篇博客的初衷首先一句话概括:我想把这几个月做的事情记录下来,并且希望尽量详细,希望读者读了这篇文章能够知道模块化具体每个步骤都做什么,而不是大致的了解。 现在很多人都在谈模块化,网上有一大堆的...
  • ES6中的模块化编程

    千次阅读 多人点赞 2020-11-29 20:55:51
    ES6中的模块化编程为什么使用模块化ES6模块化实现export 命令import命令完整实例export default 命令 为什么使用模块化 历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,...
  • JS模块化编程

    千次阅读 2015-07-14 22:29:29
    然而由于出身的缘故,JS本身在大规模应用上存在着很多问题,比如模块化编程。本文以浏览器端模块化编程为内容,重点介绍AMD规范和CMD规范。在服务器端,NodeJS遵守的Common规范我们这里暂不讨论。  对于计算机语言...
  • JS模块化和使用

    千次阅读 多人点赞 2020-08-13 08:38:37
    JS模块化和使用 很久以前就知道js模块化开发可以使用require.js和sea.js,就一直没去看看。最近在了解查看的,度一下require.js相关的博客和文章,写得真是操蛋的疼,都是互相抄来抄去,博主应该都没有自己实际去敲...
  • 模块化设计实例

    千次阅读 2015-07-28 12:09:19
    模块化设计 实例一 1 pdf文件上传下载app: 按申报类型划分功能模块;每个模块功能相同,接收传到服务器上的文件。 2 年度报告管理系统 1)数据导入导出: a 扫码导入特定数据到系统;默认导入数据库...
  • 模块化与组件化–多模块区分编译 示例地址:https://github.com/JackyAndroid/Android-Architecture-Fairy/tree/master/multi-variants-library Android-Architecture-Fairy开源项目重点分析主流技术与架构设计,...
  • 普通html文档使用ES6模块

    千次阅读 2018-09-24 11:38:00
    在以前的前端技术发展中是没有模块的概念,早期的开发中,如果要实现模块化的使用,是要通过script标签引入才能使用,但是不可避免要想使用不同的标签内的变量或者封装好的插件,则需要将构造函数或者变量通过window来...
  • iOS应用组件化/模块化探究

    千次阅读 2019-01-09 14:48:35
    组件是近几年流行起的概念,它是当代码扩张到一定程度时,所采取的一种代码组织架构策略。淘宝、蘑菇街等大厂也在近几年陆续完成了其代码组件的过程。 提到组件,给人的感觉似乎很高大上,很神秘的感觉。但是...
  • 什么是前端模块化

    千次阅读 2019-06-11 18:30:16
    前端模块化 模块化: 是具有特定功能的一个对象( 广义理解 ) 模块定义的流程: 1.定义模块(对象) 2.导出模块 3.引用模块 好处:可以存储多个独立的功能块,复用性高 种类: AMD( require.js) CMD ( sea.js ) ...
  • 软件模块化设计的思路

    万次阅读 2017-10-24 22:08:50
    本文讨论了软件模块化设计过程中的若干重要问题解决的一般思路。 【关键词】软件模块化设计、职责分离原则、可移植性、稳定性 一、问题的提出 软件模块化的目的是建立可重用的软件组件,在不需要修改或仅作少量...
  • 一文彻底搞懂前端模块化:exports、module.exports、export、import、export default CommonJS规范、ES Module规范
  • Android 模块化完整方案实现

    万次阅读 2017-12-16 22:48:06
    因为公司业务太多,代码越来越臃肿,越来越难维护,为了提升开发效率,减低代码的维护成本,所以采取了模块化开发方案。 既然是模块化开发,必然要考虑到各个module的开发,调试,迭代拓展及维护,module之间不仅...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 450,109
精华内容 180,043
关键字:

文档模块化