模块化_模块化工 - CSDN
模块化 订阅
模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程,有多种属性,分别反映其内部特性。 展开全文
模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程,有多种属性,分别反映其内部特性。
信息
外文名
Module
基本属性
接口、功能、逻辑、状态
定    义
可管理模块的方式
中文名
模块化
运行模式
独立的工作运行模式
模块化定义
模块化是一种处理复杂系统分解为更好的可管理模块的方式。 [1] 
收起全文
  • 什么是模块化 简单地说,模块化就是有组织地把一个大文件拆成独立并互相依赖的多个小模块。 模块内部有许多私有属性,只向外暴露一部分公开的接口(如可以修改私有属性的方法等) 模块化是一种处理复杂系统分解为更好...

    什么是模块化

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

    使用模块化开发好处

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

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

    展开全文
  • 模块化编程理解

    2016-09-06 18:05:23
    在上一个项目中通过对象和其中的方法实现了简单的模块化编程。但随着工程项目的庞大程度增加,简单的对象已经满足不了模块化编程的需求了,所以接触了RequireJS,了解了AMD编程规范。什么是AMD和AMD对应的是CMD,在...

    背景

    工作中在做客户运营系统时,发现js和css的引用还处于最原始的状态没有更新。在上一个项目中通过对象和其中的方法实现了简单的模块化编程。但随着工程项目的庞大程度增加,简单的对象已经满足不了模块化编程的需求了,所以接触了RequireJS,了解了AMD编程规范。

    什么是AMD

    和AMD对应的是CMD,在nodeJS里面的依赖是基于CMD,同步加载要依赖的文件。而在浏览器中,如果同步加载需要依赖的文件会导致阻塞,造成浏览器假死,所以需要进行异步依赖。AMD-Asychronous Module Loader,支持这个规范的一个库是requirejs,可以用于优化代码。

    从小了说,在做几个简单页面构成的小应用程序时,调用一个js,用不同的对象把各个方法封装起来,也是模块化的一种实现。但这更偏向业务层,涉及到其他其他第三方控件时,就会变得不好管理。

    RequireJS使用

    requirejs demo

    1. 创建一个应用程序,moduletest,工程的目录如下

      |---index.html
      |---app.js
      |---lib
      |-------require.js
      |----|---modules
      |----|------|------math.js
      
    2. 在index.html中添加requirejs

      data-main指出了入口js,类似于C++中的main函数。可以忽略js后缀。

    3. data-main所在的目录是baseurl,所有的require里面的路径都是相对于它的相对路径,当然也可以在require.config里面指定baseUrl,这样path就是以指定的baseUrl为准了。

    4. 这个app要实现的功能是当用户输入两个数字之后,显示结果。app.js注册求和按钮事件,再调用math.add求和。
    5. 在math中写入以下代码:
    define([],function(){
        var add = function(a,b){
            return parseInt(a)+ parseInt(b);
        };
    
        return{
            add:add
        }
    });

    具体的函数实现写在define函数中,第一个参数是需要引用的模块,为赋新词强说愁,引用了jquery,然后实现了add函数,return的结果是一个对象,里面包含需要返回的方法。

    6.在app中引用math,调用其方法。

    require.config({
        paths:{
            'jquery':"http://libs.ainemo.com/jquery/2.2.2/jquery.min"//注意path后面的js需要省略
        }
    });

    因为要用到公用的已经存放在cdn上比较稳定的jquery版本,所以在这里指定了jquery的路径。

    require(['jquery','lib/modules/math'],function($,math){
        $(function(){
           $('#add').click(function(){
               var result = math.add($('#param1').val() , $('#param2').val());
               $('#addResult').html(result);
           });
        });
    });

    demo done.
    demo 地址:https://coding.net/u/fiona2016/p/requirejs-learn/git

    展开全文
  • 前言  在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 规范,成为浏览器和服务器通用的模块解决方案。

    展开全文
  • 模块化开发简述

    2018-08-14 11:52:43
    模块化开发简述 都说模块化开发为前端发展带来了巨大的进步,然而不熟悉的人看着也是两眼一懵,那其实这到底是什么?好处在哪?我来说说自己的见解吧。 1. 模块化和传统开发的区别 实话讲,其实在我看来,...

    模块化开发简述

    都说模块化开发为前端发展带来了巨大的进步,然而不熟悉的人看着也是两眼一懵,那其实这到底是什么?好处在哪?我来说说自己的见解吧。
    这里写图片描述
    1. 模块化和传统开发的区别
    实话讲,其实在我看来,两者的开发是一样的,除了方式不一样,达到的效果并没两样。
    看着扯淡,但实际可以想一下,现流行的模块化开发主要有两种方式:

    • 依赖加载。这种方式是最广泛的,像requirejs,sea.js等,除了 编写规范 不一样,实际都是通过相关require api把模块chunk文件拿回来,当加载完成之后再运行逻辑代码。
    • 依赖打包。经典代表就是webpack,其实就是写代码的时候分开模块,但打包的时候按依赖关系找到各个模块,最后打包到同一个文件上,并给每个chunk标识id,运行逻辑代码时将模块引用指向该id,从而实现模块化。

    而传统的开发方式是在页面上通过脚本标签引入,等所有脚本资源加载完成后再运行逻辑代码。这样一对比,是不是发现效果其实是一样的,我把不同脚本分开写,也是可以做到类似模块化的效果?

    那么重点来了,模块化的优势在哪?

    别急着回答,先思考一下,然后带着你的想法继续看下去。

    这里写图片描述

    先回想一下,传统开发的痛点在哪。

    首先,如上所述,传统的开发方式需要等待所有脚本资源加载完成。这个问题最大的弊端就是页面要等待,因为资源加载是同步的。你的页面会出现短暂的空白期,引入的脚本越多,时间越长,如果某一脚本加载失败,也可能直接挂掉。

    模块化的代码则可以很好的处理这个问题。除了模块化支持的脚本必须加载进来以外,其他脚本都可以异步请求,不需要页面等待,可以加速渲染出页面。requirejs,sea.js等也会做好加载重试和模块缓存的处理,确保所有模块运行良好。

    所有资源加载的时间不会因为模块化而加速,但是模块化能加速渲染,这是优势1

    当然webpack是特例,它和nodejs一样用 commonjs 规范,为了达到目的,全部脚本打包到一起再运行,看着和上面观点相悖,不过现在带宽足够,相对而言还是足够快的,也能减少多脚本加载出错的风险。


    接着上面的观点讲,抛开带宽速度来讲,既然网速够快,那模块化还有什么?不妨回想一下,传统开发时最烦的是什么?无非3点

    • 命名空间。早期为了避免命名冲突,大众做法是用一个变量作为命名空间做隔离,长期开发过程中没人能记住这个变量是否冲突,它的命名规范是什么,治标不治本。
      而模块化的出现消除了这点。一个模块内的命名随自己起,和外界不会冲突,对外的永远是你exports出来的内容。如果模块内出现命名冲突,这说明了你的命名水平太低…..
      这里写图片描述
      好吧,是模块颗粒不够小,还可以继续分割出模块~

    • 代码重用。其实这点和传统开发并无两样,都是把可复用代码抽取出function(再通用点会抽象出类,也就是构造函数),独立文件。但模块化的好处同样可以规避命名空间的问题,不必设置变量污染到全局。一般模块化都有缓存机制,在二次调用时无需再解析,直接获取到缓存模块内容。

    • 懒~ 这里写图片描述
      按传统开发来处理,忽略以上问题,但也耐不住文件太多,引入和管理麻烦。除了amd规范需要依赖前置,我们还可以用cmd规范来写模块依赖,想用什么require什么,不用再一个个引入js,看着也舒服。而且现在的模块化工具基本都实现了多规范混搭,想怎么写就怎么写,只要注意组内规范就行。



    此外就是 管理问题

    小公司或个人开发,模块化能让自己思路更为清晰,降低代码耦合,优秀的模块能带来代码质量质的飞跃,标准的模块应该是 “分工明细,职责单一,不牵扯需求逻辑” ,它就应该是个万能的螺丝,不需要可以修改,哪里需要用哪里。

    而中型企业和大团队则很经常会遇到团队协作开发,除了会用svn/git等工具管理,各种需求有不同的人负责处理。模块化对团队开发会起到协同作用,公共模块除了避免重复造轮子的痛苦外,也避免了逻辑混淆。



    好了,大概就上面这些,我现阶段的水平限制了我的眼界和理解,后面有不一样的看法时再修正补充吧。
    这里写图片描述

    展开全文
  • 模块化

    2019-07-08 21:12:59
    webpack 定义 将系统功能分离成独立的功能部分的方法,分离出去的每一个部分,都可以看成一个模块。即一个js文件里有一定... 做模块化时,最终需要将各个文件组合在一起,所以需要入口文件 模块在合并时有很...
  • 什么是模块化模块化的好处是? 模块化是一种处理复杂系统分解为更好的可管理模块的方式。 所谓的模块化开发就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能。模块化开发的基础...
  • CommonJS、AMD、NodeJS、RequireJS、SeaJS、curljs等模块化的JavaScript扑面而来。web前端已经演变成大前端,web前端的发展速度之快。1)我们来看看什么是模块化模块化是一种将系统分离成独立功能部分的方法,可将...
  • 当你看到这的时候,想必心理一阵恶寒:模块化?组件化?到底是什么鬼?有啥区别. 有这种感觉才是对的,模块化和组件化本质思想是一样的,都是"大化小",两者的目的都是为了重用和解耦,只是叫法不一样.如果非要说区别,那么...
  • 当你在一个项目小组做一个相对较复杂的工程时,意味着你不再独自单干。你需要和你的小组成员分工合作,一起完成项目,这就要求小组成员各自负责一部分工程。比如你可能只是负责通讯或者...模块化的好处是很多的,不仅
  • 6. 模块化设计 6.1 样式的作用域──页面重构中的模块化设计(一) 模块化设计我已经提过很多了,都是跟模块化相关的,不过之前一直没有讲到具体实现方面的内容,只是一些思维。这次重点讲一下实现方面的内容,权...
  • 对于组件化,有的人也喜欢称之为模块化开发,我也比较喜欢称之为模块化开发。使用模块化开发也已经有一段时间了,特此总结一下模块化开发的心得,防止以后忘记。 什么是模块化开发 对于模块化开发的概念,有的人...
  • 如何实现css模块化

    2019-02-14 13:49:17
    模块化目前在前端的日常开发中已经不是什么新鲜词,早期的AMD规范的requirejs,CMD规范的seajs,以及nodejs的模块化规范commonjs,但是css的模块化一直进展不大,虽然有想less,sass,postcss…的出先,但是这些只是...
  • 什么是模块化模块化开发如何实现? 那么什么是模块化呢,时下流行的库与框架又有哪些在利用模块化进行开发呢? 今天我从以下两个方向来进行描述,如果描述不够准确,还请各位多多指正。 1.什么是模块化? ...
  • 组件化开发和模块化开发概念辨析 网上有许多讲组件化开发、模块化开发的文章,但大家一般都是将这两个概念混为一谈的,并没有加以区分。而且实际上许多人对于组件、模块的区别也不甚明了,甚至于许多博客文章专门...
  • 在学习模块化的过程中,也在不断思考,同时和一些模块化方案的作者进行了一些交流,记录下自己的一些心得体会。为什么要使用模块化,使用什么样的模块化?我认为使用模块化的原因,从代码层面考虑精髓就是解耦合,从...
  • 因为公司业务太多,代码越来越臃肿,越来越难维护,为了提升开发效率,减低代码的维护成本,所以采取了模块化开发方案。 既然是模块化开发,必然要考虑到各个module的开发,调试,迭代拓展及维护,module之间不仅...
  • 模块化和组件化是为工程化思想下相对较具体的开发方式,因此可以简单的认为模块化和组件化是工程化的表现形式。 前端工程化分为三个大阶段 技术选型 构建优化 模块化开发,组件化开发 模块化     ...
  • Python模块化编程

    2020-01-14 10:53:43
    模块化 自定义模块 模块的内置属性 导入模块 安装第三方模块 查看模块的属性和方法 模块化 在Python中,一个.py文件就称之为一个模块(Module),为了避免模块名冲突,Python又引入了按目录来组织模块的方法,...
  • 模块化开发怎么做?

    2018-08-09 16:59:33
    模块化开发 首先我们要知道什么是模块化开发? 1. 模块就是一个有特定功能的文件,我们可以通过加载这些模块得到特定的功能 2. 模块化开发就是js的功能分离,通过需求引入不同的文件 3. 模块化开发可以使代码...
  • 1什么是模块化 模块化编程就是把我们的一整个项目,分成很多模块(比如一个学生成绩查询可以分为,登陆,查询,修改保存,退出等模块) 而一个程序工程包含多个源文件(.c 文件和 .h 文件),每个 .c 文件可以被称为...
1 2 3 4 5 ... 20
收藏数 1,291,329
精华内容 516,531
关键字:

模块化