模块化_模块化编程 - CSDN
模块化 订阅
模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程,有多种属性,分别反映其内部特性。 展开全文
模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程,有多种属性,分别反映其内部特性。
信息
外文名
Module
基本属性
接口、功能、逻辑、状态
定    义
可管理模块的方式
中文名
模块化
运行模式
独立的工作运行模式
模块化定义
模块化是一种处理复杂系统分解为更好的可管理模块的方式。 [1] 
收起全文
精华内容
参与话题
  • 什么是模块化模块化的好处

    千次阅读 2019-07-15 21:16:37
    什么是模块化 简单地说,模块化就是有组织地把一个大文件拆成独立并互相依赖的多个小模块。 模块内部有许多私有属性,只向外暴露一部分公开的接口(如可以修改私有属性的方法等) 模块化是一种处理复杂系统分解为更好...

    什么是模块化

    简单地说,模块化就是有组织地把一个大文件拆成独立并互相依赖的多个小模块。
    模块内部有许多私有属性,只向外暴露一部分公开的接口(如可以修改私有属性的方法等)
    模块化是一种处理复杂系统分解为更好的可管理模块的方式。
    所谓的模块化开发就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能。模块化开发的基础就是函数。模块化开发使代码耦合度降低,模块化的意义在于最大化的设计重用,以最少的模块、零部件,更快速的满足更多的个性化需求。
    模块化的好处
    ES6之前,JavaScript语言一直没有模块(module)体系,无法把大文件有组织地划分成小块,并管理之间地依赖。但是模块化的思想一直存在。因为用Javascript写的代码越来越庞大,而网页也越来越像桌面APP。如此庞杂的代码,如果不进行模块化,就可能引发命名冲突,造成不易复用、维护性高。

    使用模块化开发好处

    1.高内聚低耦合,有利于团队作战,当项目很复杂的时候,将项目划分为子模块分给不同的人开发,最后再组合在一起,这样可以降低模块与模块之间的依赖关系体现低耦合,模块又有特定功能体现高内聚。

    2.可重用,方便维护,模块的特点就是有特定功能,当两个项目都需要某种功能的时候,我们定义一个特定的模块来实现该功能,这样只需要在两个项目中都引入这个模块就能够实现该功能,不需要书写重复性的代码;并且当需求变更该功能需要改变的时候,我们直接修改该模块,这样就能够修改所有项目的功能,维护起来很方便。
    3、通过 exports 暴露接口。这意味着不需要命名空间了,更不需要全局变量。这是一种彻底的命名冲突解决方案。
    4、通过 require 引入依赖。**这可以让依赖内置,开发者只需关心当前模块的依赖,其他事情 Sea.js/ Require.js 都会自动处理好

    展开全文
  • 前言  在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,...

    https://mp.weixin.qq.com/s/29itDAl5j11ofooVcXbOig

    前言

      在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀,此时在JS方面就会考虑使用模块化规范去管理。

      本文内容主要有理解模块化,为什么要模块化,模块化的优缺点以及模块化规范,并且介绍下开发中最流行的CommonJS, AMD, ES6、CMD规范。本文试图站在小白的角度,用通俗易懂的笔调介绍这些枯燥无味的概念,希望诸君阅读后,对模块化编程有个全新的认识和理解!

     一、模块化的理解

      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 = value或exports.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, 并引入

    • 官网: http://seajs.org/

    • github : https://github.com/seajs/seajs

      然后将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 规范,成为浏览器和服务器通用的模块解决方案。

    展开全文
  • 嵌入式C语言之---模块化编程

    万次阅读 多人点赞 2015-06-09 20:58:39
    当你在一个项目小组做一个相对较复杂的工程时,意味着你不再独自单干。你需要和你的小组成员分工合作,一起完成项目,这就要求小组成员各自负责一部分工程。比如你可能只是负责通讯或者...模块化的好处是很多的,不仅

    当你在一个项目小组做一个相对较复杂的工程时,意味着你不再独自单干。你需要和你的小组成员分工合作,一起完成项目,这就要求小组成员各自负责一部分工程。比如你可能只是负责通讯或者显示这一块。这个时候,你就应该将自己的这一块程序写成一个模块,单独调试,留出接口供其它模块调用。最后,小组成员都将自己负责的模块写完并调试无误后,由项目组长进行组合调试。像这些场合就要求程序必须模块化。模块化的好处是很多的,不仅仅是便于分工,它还有助于程序的调试,有利于程序结构的划分,还能增加程序的可读性和可移植性。

    初学者往往搞不懂如何模块化编程,其实它是简单易学,而且又是组织良好程序结构行之有效的方法之一.

    本文将先大概讲一下模块化的方法和注意事项,最后将以初学者使用最广的keil c编译器为例,给出模块化编程的详细步骤。

    模块化程序设计应该理解以下概述:

    (1) 模块即是一个.c 文件和一个.h 文件的结合,头文件(.h)中是对于该模块接口的声明;

    这一条概括了模块化的实现方法和实质:将一个功能模块的代码单独编写成一个.c文件,然后把该模块的接口函数放在.h文件中.举例:假如你用到液晶显示,那么你可能会写一个液晶驱动模块,以实现字符、汉字和图像的现实,命名为: led_device.c,该模块的.c文件大体可以写成:

    /*************************************************************************
    * 液晶驱动模块
    *
    * 文 件: lcd_device.c
    * 编 写 人: 小瓶盖
    * 描 述:液晶串行显示驱动模块,提供字符、汉字、和图像的实现接口
    * 编写时间: 2009.07.03
    * 版 本:1.2
    *************************************************************************/
    #include …
    …
    //定义变量
     unsigned char value;//全局变量
    …
    //定义函数
    //这是本模块第一个函数,起到延时作用,只供本模块的函数调用,所以用到static关键字修饰
    /********************延时子程序************************/
    static void delay (uint us) //delay time
    {}
    //这是本模块的第二个函数,要在其他模块中调用
    /*********************写字符程序**************************
    ** 功能:向LCD写入字符
    ** 参数:dat_comm 为1写入的是数据,为0写入的是指令
    content 为写入的数字或指令
    ******************************************************/
    void wr_lcd (uchar dat_comm,uchar content)
    {}
    ……
    ……
    /***************************** END Files***********************************/

    注:此处只写出这两个函数,第一个延时函数的作用范围是模块内,第二个,它是其它模块需要的。为了简化,此处并没有写出函数体.

    .h文件中给出模块的接口.在上面的例子中, 向LCD写入字符函数:wr_lcd (uchar dat_comm,uchar content)就是一个接口函数,因为其它模块会调用它,那么.h文件中就必须将这个函数声明为外部函数(使用extrun关键字修饰),另一个延时函数:void delay (uint us)只是在本模块中使用(本地函数,用static关键字修饰),因此它是不需要放到.h文件中的。

    .h文件格式如下:

    /*****************************************************************************
    * 液晶驱动模块 头文件
    *
    * 文 件: lcd_device.h
    * 编 写 人: 小瓶盖
    * 编写时间: 2010.07.03
    * 版 本:1.0
    *********************************************************************************/
    //声明全局变量
    extern unsigned char value;
    //声明接口函数
    extern void wr_lcd (uchar dat_comm,uchar content); //向LCD写入字符
    ……
    /***************************** END Files***********************************/

    这里注意三点:

    1. 在keil 编译器中,extern这个关键字即使不声明,编译器也不会报错,且程序运行良好,但不保证使用其它编译器也如此。强烈建议加上,养成良好的编程规范。

    2. .c文件中的函数只有其它模块使用时才会出现在.h文件中,像本地延时函数static void delay (uint us)即使出现在.h文件中也是在做无用功,因为其它模块根本不去调用它,实际上也调用不了它(static关键字的限制作用)。

    3.注意本句最后一定要加分号”;”,相信有不少同学遇到过这个奇怪的编译器报错: error C132: 'xxxx': not in formal parameter list,这个错误其实是.h的函数声明的最后少了分号的缘故。

    模块的应用:假如需要在LCD菜单模块lcd_menu.c中使用液晶驱动模块lcd_device.c中的函数void wr_lcd (uchar dat_comm,uchar content),只需在LCD菜单模块的lcd_menu.c文件中加入液晶驱动模块的头文件lcd_device.h即可.

    /***************************************************************************
    * 液晶菜单模块
    *
    * 文 件: lcd_menu.c
    * 编 写 人: 小瓶盖
    * 说 明:LCD菜单模块,最多实现256级菜单,与硬件无关。
    * 编写时间: 2010.07.03
    * 版 本:1.0
    **************************************************************************/
    #include“lcd_device.h //包含液晶驱动程序头文件,之后就可以在该.c文件中调用//lcd_device.h中的全局函数,使用液晶驱动程序里的全局//变量(如果有的话)。
    …
    //调用向LCD写入字符函数
    wr_lcd (0x01,0x30);
    …
    //对全局变量赋值
    value=0xff;
    …

    (2) 某模块提供给其它模块调用的外部函数及数据需在.h 中文件中冠以extern 关键字声明;

    这句话在上面的例子中已经有体现,即某模块提供给其它模块调用的外部函数和全局变量需在.h 中文件中冠以extern 关键字声明,下面重点说一下全局变量的使用。使用模块化编程的一个难点(相对于新手)就是全局变量的设定,初学者往往很难想通模块与模块公用的变量是如何实现的,常规的做法就是本句提到的,在.h文件中外部数据冠以extern关键字声明。比如上例的变量value就是一个全局变量,若是某个模块也使用这个变量,则和使用外部函数一样,只需在使用的模块.c文件中包含#include“lcd_device.h”即可。

    另一种处理模块间全局变量的方法来自于嵌入式操作系统uCOS-II,这个操作系统处理全局变量的方法比较特殊,也比较难以理解,但学会之后妙用无穷,这个方法只需用在头文件中定义一次。方法为:

    在定义所有全局变量(uCOS-II将所有全局变量定义在一个.h文件内)的.h头文件中:

    #ifdef xxx_GLOBALS
    #define xxx_EXT
    #else
    #define xxx_EXT extern
    #endif

    .H 文件中每个全局变量都加上了xxx_EXT的前缀。xxx 代表模块的名字。

    该模块的.C文件中有以下定义:

    #define xxx_GLOBALS
    #include "includes.h"

    当编译器处理.C文件时,它强制xxx_EXT(在相应.H文件中可以找到)为空,(因为xxx_GLOBALS已经定义)。所以编译器给每个全局变量分配内存空间,而当编译器处理其他.C 文件时,xxx_GLOBAL没有定义,xxx_EXT 被定义为extern,这样用户就可以调用外部全局变量。为了说明这个概念,可以参见uC/OS_II.H,其中包括以下定义:

    #ifdef OS_GLOBALS
    #define OS_EXT
    #else
    #define OS_EXT extern
    #endif
    OS_EXT INT32U OSIdleCtr;
    OS_EXT INT32U OSIdleCtrRun;
    OS_EXT INT32U OSIdleCtrMax;

    同时,uCOS_II.H 有中以下定义:

    #define OS_GLOBALS

    #include “includes.h”

    当编译器处理uCOS_II.C 时,它使得头文件变成如下所示,因为OS_EXT 被设置为空。

    INT32U OSIdleCtr;

    INT32U OSIdleCtrRun;

    INT32U OSIdleCtrMax;

    这样编译器就会将这些全局变量分配在内存中。当编译器处理其他.C 文件时,头文件变成了如下的样子,因为OS_GLOBAL没有定义,所以OS_EXT 被定义为extern。

    extern INT32U OSIdleCtr;

    extern INT32U OSIdleCtrRun;

    extern INT32U OSIdleCtrMax;

    在这种情况下,不产生内存分配,而任何 .C文件都可以使用这些变量。这样的就只需在 .H文件中定义一次就可以了。

    (3) 模块内的函数和全局变量需在.c 文件开头冠以static 关键字声明;

    这句话主要讲述了关键字static的作用。Static是一个相当重要的关键字,他能对函数和变量做一些约束,而且可以传递一些信息。比如上例在LCD驱动模块.c文件中定义的延时函数static void delay (uint us),这个函数冠以static修饰,一方面是限定了函数的作用范围只是在本模块中起作用,另一方面也给人传达这样的信息:该函数不会被其他模块调用。下面详细说一下这个关键字的作用,在C 语言中,关键字static 有三个明显的作用:

    1.在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

    2.在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变

    量。

    3.在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

    前两个都比较容易理解,最后一个作用就是刚刚举例中提到的延时函数(static void delay (uint us)),本地化函数是有相当好的作用的。

    (4) 永远不要在.h 文件中定义变量!

    呵呵,似乎有点危言耸听的感觉,但我想也不会有多少人会在.h文件中定义变量的。

    比较一下代码:

    代码一:

    /*module1.h*/
    int a = 5; /* 在模块1 的.h 文件中定义int a */
    /*module1 .c*/
    #include "module1.h" /* 在模块1 中包含模块1 的.h 文件 */
    /*module2 .c*/
    #include "module1.h" /* 在模块2 中包含模块1 的.h 文件 */
    /*module3 .c*/
    #include "module1.h" /* 在模块3 中包含模块1 的.h 文件 */

    以上程序的结果是在模块1、2、3 中都定义了整型变量a,a 在不同的模块中对应不同的地址元,这个世界上从来不需要这样的程序。正确的做法是:

    代码二:

    /*module1.h*/
    extern int a; /* 在模块1 的.h 文件中声明int a */
    /*module1 .c*/
    #include "module1.h" /* 在模块1 中包含模块1 的.h 文件 */
    int a = 5; /* 在模块1 的.c 文件中定义int a */
    /*module2 .c*/
    #include "module1.h" /* 在模块2 中包含模块1 的.h 文件 */
    /*module3 .c*/
    #include "module1.h" /* 在模块3 中包含模块1 的.h 文件 */

    这样如果模块1、2、3 操作a 的话,对应的是同一片内存单元。

    注:

    一个嵌入式系统通常包括两类(注意是两类,不是两个)模块:

    (1)硬件驱动模块,一种特定硬件对应一个模块;

    (2)软件功能模块,其模块的划分应满足低偶合、高内聚的要求。

    下面以keil C 编译器为例,讲一下模块化编程的步骤。

    下面这个程序分为三层,共7个模块,共同为主程序服务(它们之间也会相互调用)。

    程序的结构图如下所示:

    clip_image001

    程序主要模块和功能简介:

    一. 底层驱动

    1. 红外键盘:程序通过红外键盘进行操作。红外键盘独占定时器0和外部中断0,以实现红外解码和键盘键值的识别。红外键盘定义了五个按键,分别为上翻、下翻、左翻、右翻和确认键。

    2. LCD液晶显示:程序主要通过LCD显示信息,LCD液晶显示驱动提供显示汉字、图形和ASCII码的函数接口。可以全屏、单行显示汉字,任意位置显示ASCII码,还可以全屏、半屏显示图形。

    二. 功能模块

    1. LCD菜单程序:菜单程序可以使人机交互更加方便、容易。本菜单程序的菜单级别深度受RAM大小的限制,每增加一级菜单将多消耗4字节的RAM。菜单程序主要完成菜单功能函数的调度,LCD显示刷新。

    2. 计算器程序:实现65536以内的加、减、乘、除,超出范围会出现溢出,溢出发生时,LCD显示“错误:出现溢出”的错误提示,同时本次运算被忽略。对于负数会显示“-”号,除数为零时LCD显示“错误:除数为零”的错误提示。

    3. 开机次数记忆程序:主要对基于IIC总线的EEPROM进行读写,单片机每次上电后,将开机次数写入EEPROM.

    4. 串口测试程序:进入该程序后,单片机向电脑发送字符串“Hello Word!”,发送数字24(以字符的形式显示)。编写此程序的目的是为了能够方便的向电脑发送字符串和变量,便于程序的调试。串口占用串口资源,与频率测量程序共享定时器1

    5. 频率测量:复用定时器1,占用外部中断1,实现5~20KHZ频率的测量.

    三. 主程序

    主程序主要完成程序的初始化,LCD菜单显示,监视键盘程序并根据键值更新菜单。

    步骤为:

    1.新建工程。

    2.点击File—New(或者点击快捷图标:clip_image003),新建一个文档。

    3.点击File—Save(或者点击快捷图标:clip_image005),保存新建的文档,在文件名后填写LCD_device.c(液晶驱动模块: LCD_device,提供显示汉字、字符和图像的接口),点击确定。

    在该文档内编写LCD驱动程序。

    4. 点击File—New(或者点击快捷图标:clip_image003[1]),再新建一个文档。

    5. 点击File—Save(或者点击快捷图标:clip_image005[1]),保存新建的文档,在文件名后填写LCD_device.h(液晶驱动模块的头文件,模块的接口和全局变量在这里声明(感谢网友杨康佳指正这里的错误,原文将“声明”写成了“定义”,头文件一般用来声明变量和接口的))。点击确定。在该文档中整理全局变量和接口函数。以上步骤之后的效果见下图:

    clip_image007

    至此,液晶驱动模块书写完毕,可以对这个模块单独的调试。

    6.重复以上步骤2~5,定义 红外键盘模块:key.c与key.h

    菜单模块:menu.c与menu.h

    串口通信模块:uart_.c与uart.h

    计算器模块:counter.c与counter.h

    频率测量模块:mea_fre.c与mea_fre.h

    开机次数记忆模块:eepram.c与eepram.h

    7.重复以上步骤2~3,定义主程序main.c

    最终效果如下图所示:

    clip_image009

    完成1~7个步骤后,有些小白就习惯性的点击编译按钮了,这时候会出现两个警告信息:

    *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL

    *** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL

    这是因为你只是编写好了程序模块,却没有把他们加入到工程的缘故。

    解决方法:在Project Workspace框中,右击Source group 1文件夹,选择Add Files to Group‘Source Group 1’,在弹出的对话框中添加你的.c文件即可。

    遥想很久很久以前,我也对上面的两个警告有过亲身体会。那时候我还在大学,周围有一大群的好哥们. 现在…想起来只剩唏嘘!!!

    展开全文
  • ES6的模块化

    2019-09-23 17:54:07
    如果你对模块化已经了解,可以直接从第三点开始阅读。 一、模块化的概念: 在进行项目分析或者编码时,先把项目进行拆分,拆分成很多的类,对象,很多的函数等等。能够提高代码的复用性。这些被拆分出来的类型,...

    如果你对模块化已经了解,可以直接从第三点开始阅读。

    一、模块化的概念:

    在进行项目分析或者编码时,先把项目进行拆分,拆分成很多的类,对象,很多的函数等等。能够提高代码的复用性。这些被拆分出来的类型,对象,函数就是模块。就像一辆汽车是由很多的零部件组成,每个零部件就是一个小模块,而由很多零件组成的发动机之于一辆汽车可以认为是一个大模块;或者说,一台计算机,由主板,cpu,内存,硬盘,显示器,键盘等大模块组成。而一个内存或者cpu又分别由很多的小模块组成。以模块为单位管理代码,会更加独立,调试方便,维护也很方便。

     

    二、模块化经历的阶段:

        1. 函数封装

    这种做法的缺点很明显:污染了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间没什么关系。不同js文件里有相同的全局变量,如果被引入到同一个html文件中,全局变量就会互相影响。

         2. 对象

    这样避免了变量污染,只要保证模块名唯一即可,同时同一模块内的成员也有了关系,看似不错的解决方案,但是也有缺陷,外部(对象之外)可以随意修改内部成员(属性)

    对象的属性就是对象中每个方法的全局变量。

    var p = {
    
        id:"007",
    
        name :"芙蓉",
    
        age:25,    
    
        eat:function(str){
    
            alert(this.name+"在吃"+str);
    
        },
    
        work:function(str){
    
            alert(this.name+“在干"+str);
    
        }           
    
    }
    
    //存在问题:
    
    //如:对于p对象的年龄,有效取值应该是在0-150之间的整数。
    
    //  而以下代码的执行,
    
    p.age = 151;
    
    都会使得项目内部出现了不合法的数据。这是程序的健壮性不好。   
    
    所以,对于对象的成员变量(属性),应该不能被外部访问才对。
    

      3.  立即执行函数

    可以通过立即执行函数,来达到隐藏细节的目的

    
    var p = (function (){
    
        var name="芙蓉";
    
        var age=25;
    
        function eat(str){
    
            alert(this.name+"在吃"+str);
    
        }
    
        function setAge(age){
    
            if(age<0 || age>150){
    
                alert("亲,年龄超出有效值(0-150)的范围");
    
                return;
    
            }
    
            age = age;
    
        }
    
        function getAge(){
    
            return age;
    
        }
    
        return {
    
            eat:eat,
    
            setAge:setAge,
    
            getAge:getAge
    
        }                   
    
    })();  
    
    var p = (function (){
    
        var name="芙蓉";
    
        var age=25;
    
        function eat(str){
    
            alert(this.name+"在吃"+str);
    
        }
    
        function setAge(age){
    
            if(age<0 || age>150){
    
                alert("亲,年龄超出有效值(0-150)的范围");
    
                return;
    
            }
    
            age = age;
    
        }
    
        function getAge(){
    
            return age;
    
        }
    
        return {
    
            eat:eat,
    
            setAge:setAge,
    
            getAge:getAge
    
        }                   
    
    })();  
    
    

        4. 模块化的解决方案。

    •  以上模块化存在的问题:

    不管是以上哪种方式(函数,对象,立即执行函数),都存在同样的问题:

    1)、html不但要引入自己需要的js文件,还需要引入js文件需要的js文件。如:a.html需要使用 b.js的代码,而由于b.js中使用了c.js里的代码。所以,在a.html中必须引入b.js和c.js。这是JavaScript语言先天性的缺陷----js文件没法引入js文件。其它编程语言(java,c#,c/c++)就不存在这个问题。

    2)、引入js文件的顺序问题以及异步加载问题。

     

    • 为此出现了一些解决方案:

     1)、前端模块化

        在前端里出现了第三方的解决方案 AMD和CMD

     2)、后端模块化

        在后端里(nodeJS)出现了commonJS规范。

     

    三、ES6的模块化:

       1、原生支持模块化了

    ES6中新增的模块化,即从ES6开始,原生js支持模块化了,现在很多浏览器也支持模块化了。

      2、模块化的两个概念

        1)、导出(export关键字):导出就是对外开放的,可以导出变量,常量,函数,对象等等。使用export关键字。放在export关键字后面的(即对外导出的)变量,常量,函数和对象,在其它js文件中可以使用,否则,其它js文件中是不能使用的。即只能内部使用的。

    在用export导出时,可以导出多个

    如:person.js文件(模块)里,如下:

    //导出字符串
    
    export var str = "hello";
    
    //导出函数
    
    export var fun = function(){
    
        alert("我是函数");
    
    }
    
    //导出对象
    
    export const p =  {
    
        "id":"007",
    
        "name":"张三疯",
    
        "eat":function(){
    
            alert("吃");
    
            ff();
    
        }
    
    }
    
    //此函数没有使用export关键字导出,所以,只能在当前js文件内部使用
    
    function ff(){
    
        alert("我只能在当前js被使用");
    
    }
    
    

    2)、导入(import):导入就是把其它js文件引入到当前js文件里。使用关键字import。

     

    在使用import导入(export导出的)时,要使用花括号,

    如:import {str,fun,p} from './person.js';

     

    在index.js文件中,引入模块person.js;

    //导入时,需要使用{},这是解构赋值。
    
    import {str,fun,p} from './person.js';
    
    window.onload = function(){
    
        document.getElementById("btn01").onclick = function(){
    
            console.log(str);
    
            fun();
    
            console.log(p.id);
    
            p.eat();
    
        }
    
    }
    
    

    3)、在html文件中引入index.js(注意: type="module")
    注意:js中使用了模块化的关键字import,在引入时,script标签的type属性的值必须写成module。即:<script type="module" src="js/index.js"></script>

     

    <body>
    
        <input id="btn01" type="button" value="测试" />
    
    </body>
    
    <script type="module" src="js/index.js"></script>
    
    

    注意:测试以上代码时,google浏览器要求放在服务器上进行 ,否则,就会有跨域问题。

    4)、export defaultexport 有什么区别:

    1. 、export与export default均可用于导出常量、函数、文件、模块等
    2. 、在一个文件或模块中,export可以有多个,export default仅有一个,而且export default在导出是不需要变量名,相当于匿名的。
    3. 、通过export方式导出,在导入时要加{ },export default则不需要。

    代码示例:

    模块定义:dog.js

    export default {
    
        "name":"大黄",
    
        "eat":function(){
    
            alert("吃");
    
        }
    
    }

    导入模块:

    import d from './dog.js';
    
    window.onload = function(){
    
        document.getElementById("btn01").onclick = function(){
    
            console.log(d);
    
            d.eat();
    
        }
    
    }
    

     

    展开全文
  • 什么是模块化模块化的好处是

    千次阅读 2019-07-15 20:25:43
    什么是模块化模块化的好处是? 模块化是一种处理复杂系统分解为更好的可管理模块的方式。 所谓的模块化开发就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能。模块化开发的基础...
  • 模块化

    2020-05-31 15:33:29
    模块化CommonJSES6 ModuleAMDCMD CommonJS 导出:module.exports module.exports = { name: 'module1', add: function (a, b){ return a + b; } } 导入:require ES6 Module 导出:export / export ...
  • 什么是模块化

    2019-09-06 14:41:05
    JS模块化 一、理解 1、什么是模块、模块化? 将一个复杂的程序依据一定的规范封装成几个文件,并进行组合在一起 2、为什么要模块化? 降低复杂度,提高解耦性,部署方便 3、模块化的好处 避免命名冲突(减少命名...
  • 模块化的方法

    2018-07-23 00:54:05
    模块化的方法 什么是模块化: 具有相同属性和行为的事物的集合。在前端中,将一些属性和行为比较类似的内容放在同一个js文件里面,把这个js文件称为模块,每个js文件各司其职。 模块要有几个特点: 独立、完整、...
  • java9已经出来有一段时间了,今天向大家介绍一下java9的一个重要特性——模块化模块化系统的主要目的如下: 更可靠的配置,通过制定明确的类的依赖关系代替以前那种易错的类路径(class-path)加载机制。 强大的...
  • 组件化开发和模块化开发概念辨析

    万次阅读 多人点赞 2018-01-29 00:58:30
    组件化开发和模块化开发概念辨析 网上有许多讲组件化开发、模块化开发的文章,但大家一般都是将这两个概念混为一谈的,并没有加以区分。而且实际上许多人对于组件、模块的区别也不甚明了,甚至于许多博客文章专门...
  • 什么是模块化模块化开发如何实现? 那么什么是模块化呢,时下流行的库与框架又有哪些在利用模块化进行开发呢? 今天我从以下两个方向来进行描述,如果描述不够准确,还请各位多多指正。 1.什么是模块化? ...
  • Verilog 模块

    万次阅读 2018-09-24 14:56:19
    模块的概念 模块(module)是verilog最基本的概念,是v设计中的基本单元,每个v设计的系统中都由若干module组成。 1、模块在语言形式上是以关键词module开始,以关键词endmodule结束的一段程序。 2、模块的实际...
  • 什么是模块化,组件化, 插件化?

    万次阅读 2018-06-01 09:31:27
    最近毕竟火的也就是组件的应用了,可以大大加快项目的开发进度,对此本人亲自做了demo,有想了解的朋友请关注:https://github.com/wangpengfei1992/ModularizedDemo 废话不多说,解释一下这几个的概念和区别的...
  • requireJS介绍

    万次阅读 2019-08-11 01:29:32
    requireJS详细介绍: http://www.runoob.com/w3cnote/requirejs-tutorial-1.html ...模块化规范: AMD - - 异步模块定义(require.js) CMD - - 通用模块定义(sea.js) CommonJS - - Nod...
  • java开发web怎么把每个功能模块化? 以前做项目 比如一个页面的数据都是在后台 一个查询函数 把数据查询出来发送到前台 然后前台显示, 但是最近做一个网站 情况是这样的 最初版 和以前一样 一个查询 把 主页很多...
  • https://wenku.baidu.com/view/7133e3837e21af45b207a865
  • 题目点评 主要考察你是否有做过比较复杂、庞大的项目,是否具备一定的编程思想。随着前端技术的发展,前端编写的代码量也越来越大,就需要对代码有很好的管理。目前比较好的开发语言就是OOP(面向对象...所谓的模块化
  • Verilog例

    万次阅读 2017-12-19 23:02:41
    模块的概念 模块(module)是verilog最基本的概念,是v设计中的基本单元,每个v设计的系统中都由若干module组成。 1、模块在语言形式上是以关键词module开始,以关键词endmodule结束的一段程序。 2、模块的...
  • 什么是模块?各个模块之后怎么连接的弄得我晕头转向,今天用一个流水灯的程序探究了一下。 首先我们看最底层的三个模块程序: module smg_scan_module //数码管选通模块 ( input sys_clk, //输入时钟和...
  • 模块化到组件化再到插件化

    万次阅读 多人点赞 2017-04-17 22:02:35
    模块化到组件化再到插件化 参考: http://blog.xiaohansong.com/2015/10/21/IoC-and-DI/ http://blog.csdn.net/dd864140130/article/details/53645290 ... ...
1 2 3 4 5 ... 20
收藏数 1,324,703
精华内容 529,881
关键字:

模块化