js模块化学习

一、可以暴露函数的方式:

1、 全局函数模式: 将不同的功能封装成不同的全局函数
问题: Global被污染了, 很容易引起命名冲突,比如两个js文件暴露的函数对象命名是相同的,在HTML同时引入时,会导致命名产生冲突。

2、 namespace模式: 简单对象封装,减少了全局变量。(用对象来暴露功能)
问题: 不安全(数据不是私有的, 外部可以直接修改)

3、 IIFE模式: 匿名函数自调用(闭包),immediately-invoked function expression(立即调用函数表达式)
作用: 数据是私有的, 外部只能通过暴露的方法操作

(function (window) {
  //数据
  let data = 'test'

  //操作数据的函数
  function foo() { //用于暴露有函数
    console.log(`foo() ${data}`)
  }

  function bar() {//用于暴露有函数
    console.log(`bar() ${data}`)
    otherFun() //内部调用
  }

  function otherFun() { //内部私有的函数
    console.log('otherFun()')
  }

  //暴露行为
  window.myModule = {foo, bar}
})(window)

4、IIFE模式增强 : 引入依赖,是现代模块实现的基石

(function (window, $) {
  //数据
  let data = 'test'

  //操作数据的函数
  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)

问题: 当HTML使用多个js文件时:

  1. 一个页面需要引入多个js文件
  2. 问题:
    1). 请求过多,需要多个js请求
    2). 依赖模糊,模块间可能会相互依赖,要求引入的顺序不能出错。
    3). 难以维护

二、js模块化

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

组成:
1、 数据—>内部的属性
2、操作数据的行为—>内部的函数
模块化:
编码时是按照模块一个一个编码的, 整个项目就是一个模块化的项目

1、CommonJS
暴露方式:
module.exports = value 向外暴露一个对象
module.exports = value 向外暴露一个函数
exports.xxx = value 向外暴露一个对象,这种方式可以在一个js文件中暴露多个对象

引入方式:
var module = require(模块名或模块路径);

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

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

exports.foo = function () {
  console.log('module3 foo()')
}

exports.bar = function () {
  console.log('module3 bar()')
}

let module1 = require('./modules/module1')
Node.js模块化,服务器端。运行时, 动态同步引入
  |-modules
    |-module1.js
    |-module2.js
    |-module3.js
  |-app.js
  |-package.json
    {
      "name": "commonJS-node",
      "version": "1.0.0"
    }
    
Browserify模块化,浏览器端  也称为js的打包工具,在运行前对模块进行编译/转译/打包的处理(已经将依赖的模块包含进来了), 运行的是打包生成的js, 运行时不存在需要再从远程引入依赖模块

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


1、module1.js
   module.exports = {
      foo() {
        console.log('moudle1 foo()')
      }
    }

2、module2.js
   module.exports = function () {
      console.log('module2()')
    }

3、module3.js
    exports.foo = function () {
      console.log('module3 foo()')
    }
    
    exports.bar = function () {
      console.log('module3 bar()')
    }


4、app.js
    let module1 = require('./module1')
    let module2 = require('./module2')
    let module3 = require('./module3')
    
    let uniq = require('uniq')
    
    //使用模块
    module1.foo()
    module2()
    module3.foo()
    module3.bar()

2、AMD-RequireJS 模块化(浏览器端)
定义暴露模块: 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']
            }
          }
        })

3、CMD-SeaJs模块化(浏览器端)
定义暴露模块:

        define(function(require, module, exports){
          通过require引入依赖模块
          通过module/exports来暴露模块
          exports.xxx = value
        })

使用模块:seajs.use([‘模块1’, ‘模块2’])

4、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模块化的语法
解决:
1、 使用Babel将ES6—>ES5(使用了CommonJS) ----浏览器还不能直接支行
2、使用Browserify—>打包处理----浏览器可以运行

猜你喜欢

转载自blog.csdn.net/qq_40844662/article/details/108529069
今日推荐