JS - JS模块化

模块化

  • 什么是模块化?

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

    • 数据——>内部的属性
    • 操作数据的行为——>内部的函数
  • 模块化的发展

    • 全局function模式

      • 编码:全局变量/函数
      • 问题:污染全局命名空间,容易引起命名冲突/数据不安全
    • namespace模式

      • 编码:将数据/行为封装在对象
      • 解决:命名冲突(减少了全局变量)
      • 问题:数据不安全(外部可以直接修改模块内部的数据
    • IIFE模式/增强

      • IIFE:立即调用函数——>匿名函数自调用

      • 编码:将数据和行为封装在一个函数内部,通过window添加属性来向外暴露接口

      • 引入依赖:通过函数形参来引入依赖模块

        (function(window, module1){
            var data = '123'
            function foo() {
                module1.xxx()
                console.log('foo()'+data)
            }
            function bar() {
                console.log('bar()'+data)
            }
            window.module = {foo}
        })(window, module1)
        
  • 模块化规范

    • CommonJS

      • Node.js:服务器端

      • Browserify:浏览器端,也称为js的打包工具

      • 基本语法:

        • 定义暴露模块:exports

          exports.xxx = value
          module.exports = value
          

          引入模块:require

          var module = require('模块名/模块相对路径')
          
        • 引入模块发生在什么时候?

          • Node:运行时,动态同步引入
          • Browserify:在运行前对模块进行编译/转义/打包的处理(已经将依赖的模块包含进来了),运行的是打包生成的js,运行时不存在需要再从远程引入依赖模块
    • AMD:浏览器端

      • require.js
      • 基本语法

        • 定义暴露模块: define([依赖模块名], function(){return 模块对象})

        • 引入模块: require(['模块1', '模块2', '模块3'], function(m1, m2){//使用模块对象})

        • 配置:

          require.config({
            //基本路径
            baseUrl : 'js/',
            //标识名称与路径的映射
            paths : {
              '模块1' : 'modules/模块1',
              '模块2' : 'modules/模块2',
              'angular' : 'libs/angular',
              'angular-messages' : 'libs/angular-messages'
            },
            //非AMD的模块
            shim : {
              'angular' : {
                  exports : 'angular'
              },
              'angular-messages' : {
                  exports : 'angular-messages',
                  deps : ['angular']
              }
            }
          })
          
    • CMD : 浏览器端

      • sea.js

      • 基本语法

        • 定义暴露模块:

          define(function(require, module, exports){
            通过require引入依赖模块
            通过module/exports来暴露模块
            exports.xxx = value
          })
          
        • 使用模块seajs.use([‘模块1’, ‘模块2’])

    • ES6

      • ES6内置了模块化的实现

      • 基本语法

        • 定义暴露模块:export

          • 暴露一个对象:

            export default 对象
            
          • 暴露多个:

            // 方法一:
            export var xxx = value1
            export let yyy = value2
            
            // 方法二:
            var xxx = value1
            let yyy = value2
            export {xxx, yyy}
            
        • 引入使用模块:import

          • default模块:

            import xxx from '模块路径/模块名'
            
          • 其它模块

            import {xxx, yyy} from '模块路径/模块名'
            import * as module1 from '模块路径/模块名'
            
      • 问题:所有浏览器还不能直接识别ES6模块化的语法

      • 解决:

        • 使用Babel将ES6转成ES5(使用了CommonJS)——此时浏览器还是不能直接执行
        • 使用Browserify进行打包处理——此时浏览器可以运行

Node.js模块化教程

  1. 下载安装node.js

  2. 创建项目结构

    |-modules
      |-module1.js
      |-module2.js
      |-module3.js
    |-app.js
    |-package.json
      {
        "name": "commonJS-node",
        "version": "1.0.0"
      }
    
  3. 下载第三方模块

    如果用到第三方模块,用npm下载

    npm i uniq --save

  4. 模块化编码

    • module1.js

      module.exports = {
        foo() {
          console.log('moudle1 foo()')
        }
      }
      
    • module2.js

      module.exports = function () {
        console.log('module2()')
      }
      
    • module3.js

      exports.foo = function () {
        console.log('module3 foo()')
      }
      
      exports.bar = function () {
        console.log('module3 bar()')
      }
      
    • app.js

      /**
        1. 定义暴露模块:
          module.exports = value;
          exports.xxx = value;
        2. 引入模块:
          var module = require(模块名或模块路径);
       */
      "use strict";
      //引用模块
      let module1 = require('./modules/module1')
      let module2 = require('./modules/module2')
      let module3 = require('./modules/module3')
      
      let uniq = require('uniq')
      let fs = require('fs')
      
      //使用模块
      module1.foo()
      module2()
      module3.foo()
      module3.bar()
      
      console.log(uniq([1, 3, 1, 4, 3]))
      
  5. 通过node运行app.js

    node app.js

Browserify模块化教程

  1. 创建目录结构

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

    • 全局:npm i browserify -g
    • 局部:npm i browserify --save-dev
  3. 定义模块代码

    同Node.js模块化编码

  4. 打包处理js

    browserify js/src/app.js -o js/dist/bundle.js

  5. 页面使用引入

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

AMD-RequireJS模块化教程

  1. 下载require.js,并引入

    • 官网: http://www.requirejs.cn/
    • github : https://github.com/requirejs/requirejs
    • 将require.js导入项目: js/libs/require.js
  2. 创建目录结构

    |-js
      |-libs
        |-require.js
      |-modules
        |-alerter.js
        |-dataService.js
      |-main.js
    |-index.html
    
  3. 定义require.js的模块化代码

    • module1.js

      define({
          msg : "这个模块他没有依赖其他模块",
          getMsg() {
              console.log(`module1 ${this.msg}`)
          }
      })
      
    • module2.js

      define(function () {
          let msg = "这个模块他没有依赖其他模块"
          function getMsg() {
              console.log(`module2 ${msg}且使用了一个函数做一些工作`)
          }
          return { getMsg }
      })
      
    • module3.js

      define(["module1", "module2", "jquery"], function (m1, m2, $) {
          let msg = '这个模块依赖了其他模块'
      
          function showMsg() {
              $('body').css('background', 'red')
              m1.getMsg()
              m2.getMsg()
          }
          return { showMsg }
      })
      
  4. 应用入口js:main.js

    (function () {
        // 配置
        requirejs.config({
            // 基本路径
            baseUrl: 'js/',
            // 模块标识名和模块路径映射
            paths: {
                // 自定义模块
                module1: 'modules/module1',
                module2: 'modules/module2',
                module3: 'modules/module3',
    
                // 第三方库模块
                jquery: 'libs/jquery'
            }
        })
    
        // 引入使用模块
        requirejs(['module3'], function (m3) {
            m3.showMsg()
        })
    })()
    
  5. 在页面使用模块

    <script data-main="js/main" src="js/libs/require.js"></script>

  6. 使用第三方基于require.js的框架(jquery)

    • 将jquery的库文件导入到项目: js/libs/jquery-1.10.1.js

    • 在main.js中配置jquery路径

      paths: {
          'jquery': 'libs/jquery-1.10.1'
      }
      
    • 在module3.js中使用jquery

      define(['dataService', 'jquery'], function (dataService, $) {
          var name = 'xfzhang'
          function showMsg() {
              $('body').css({background : 'red'})
              alert(name + ' '+dataService.getMsg())
          }
          return {showMsg}
      })
      
  7. 使用第三方不基于require.js的框架(angular)

    • 将angular.js导入项目

    • js/libs/angular.js

    • 在main.js中配置

      (function () {
        require.config({
          //基本路径
          baseUrl: "js/",
          //模块标识名与模块路径映射
          paths: {
            //第三方库
            'jquery' : './libs/jquery-1.10.1',
            'angular' : './libs/angular',
            //自定义模块
            "alerter": "./modules/alerter",
            "dataService": "./modules/dataService"
          },
          /*
           配置不兼容AMD的模块
           exports : 指定与相对应的模块名对应的模块对象
           */
          shim: {
            'angular' : {
              exports : 'angular'
            }
          }
        })
        //引入使用模块
        require( ['alerter', 'angular'], function(alerter, angular) {
          alerter.showMsg()
          console.log(angular);
        })
      })()
      

CMD-SeaJS模块化教程

  1. 下载sea.js,并引入

    • 官网: http://seajs.org/
    • github : https://github.com/seajs/seajs
    • 将sea.js导入项目: js/libs/sea.js
  2. 创建项目结构

    |-js
      |-libs
        |-sea.js
      |-modules
        |-module1.js
        |-module2.js
        |-module3.js
        |-module4.js
        |-main.js
    |-index.html
    
  3. 定义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)
        })
      })
      
  4. 入口模块:main.js

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

    <!--
    使用seajs:
      1. 引入sea.js库
      2. 如何定义导出模块 :
        define()
        exports
        module.exports
      3. 如何依赖模块:
        require()
      4. 如何使用模块:
        seajs.use()
    -->
    <script type="text/javascript" src="js/libs/sea.js"></script>
    <script type="text/javascript">
      seajs.use('./js/modules/main')
    </script>
    

ES6模块化教程

ES6-Babel-Browserify

  1. 创建项目结构

    |-js
      |-src
        |-app.js
        |-module1.js
        |-module2.js
        |-module3.js
    |-index.html
    |-babel.config.json
    |-package.json
    
  2. 安装babel相关包和browserify

    babel官网:https://www.babeljs.cn/docs/usage

    • npm i --save-dev @babel/core @babel/cli @babel/preset-env
    • npm i browserify -g + npm i browserify --save-dev
  3. 在根目录下定义babel.config.json文件

    {
        "presets": ["@babel/preset-env"] 
    }
    
  4. 编码

    • module1.js分别暴露

      export function foo() {
          console.log(`module1 foo()`)
      }
      export function bar() {
          console.log(`module1 bar()`)
      }
      export const DATA_ARR = [1, 2, 3, 4, 5]
      
    • module2.js统一暴露

      let data = "module2 data"
      function fun1() {
          console.log(`module2 fun1 ${data}`)
      }
      function fun2() {
          console.log(`module2 fun2 ${data}`)
      }
      export { fun1, fun2 }
      
    • module3.js默认暴露

      export default {
          name: 'default',
          setName(name) {
              this.name = name
          }
      }
      
    • app.js

      import { foo, bar, DATA_ARR } from './module1'
      import { fun1, fun2 } from './module2'
      import person from './module3'
      
      import $ from 'jquery'
      
      $('body').css('background', 'pink')
      
      foo()
      bar()
      console.log(DATA_ARR)
      fun1()
      fun2()
      
      person.setName('默认')
      console.log(person.name)
      
  5. 编译

    • 使用Babel将ES6编译为ES5代码(但包含CommonJS语法):
      • 方法一:./node_modules/.bin/babel js/src --out-dir js/lib
      • 方法二:npx babel js/src --out-dir js/lib
    • 使用Browserify编译js:
      • browserify js/lib/app.js -o js/lib/bundle.js
  6. 页面中引入测试

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

  7. 引入第三方模块(jQuery)

    • 下载jQuery模块:npm i jquery@1 --save

    • 在app.js中引入并使用

      import $ from 'jquery'
      $('body').css('background', orange)
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值