前端开发

JavaScript - 关于 CommonJs AMD CMD

2019-03-12  本文已影响0人  人话博客

模块无非就是把一些通用的定义成文件.
起到复用,结构层次清晰,后期好维护等好处.

不管是什么 CommonJS , AMD 还是 CMD.
最主要的就是要先摸清三个事情.


CommonJS

Node.js 实现了 CommonJS 的模块化规范.(跑在后台服务器的)

CommonJs 提供了四个环境变量,为模块化提供了支持.(模块是怎么定义以及怎么使用的)

实际使用时

一般推荐使用 module.export = {} 的方式.而非 exports.xxx


// 定义 math.js 模块.

function plus(num1,num2) {
    return num1 + num2
}

// exports.plus = plus 不推荐这种写法.

module.exports = {
    plus
}

// 使用 math.js 模块
// main.js

const math = require('./math')
math.plus(1,2)

CommonJs 使用同步的方式加载模块.
模块执行的环境在本地的服务器的Node环境中.

一切都是这么的和谐自然.

一般后端开发语言都包含模块.

比如:


AMD & RequireJS

AMD 全称是 Asynchronous Module Definition.

AMD 模块是跑在浏览器环境中的.(跑在前端浏览器中的)

AMD 规范采用了异步的方式加载模块,模块的加载不影响它后续的语句执行.
所以依赖这个模块的语句,都定义在后面的那个回调函数中.
并以参数的形式提供.
等到所有依赖的模块都加载完毕之后,这个回调函数才会执行.

它是浏览器端的一种模块化异步加载的规范.

requireJS 实现了 AMD 的这套标准.

使用 requireJS 提供的几个简单的 API 接口,就可以让我们实现前端模块化的开发.(模块怎么定义以及怎么使用的.)

当然,这里的前端化组件开发,肯定就是不之间的那种多个 <script></script> 按顺序导入的那种情况了.
AMD 实际会根据 define() 或者 require() 中依赖的模块内容,异步的加载对应的js文件.

step 1

首先要去 requireJS 官网下载 requirejS 文件.

step 2

新建一个 index.html,并导入我们下载好的这个 requireJS .

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>AMD-Asynchronous Module Definition</title>
</head>
<body>
  <div id="app"></div>
</body>
</html>
<!-- 导入 require.js -->
<script src="./js/require.js" async="true" defer data-main="./js/main.js"></script>

其中

这里的

<script src="./js/require.js" async="true" defer data-main="./js/main.js"></script>

做了两件事情:

step 3

定义一个 main.js 需要使用到的模块.

既然这里使用到的是 requirejs 提供的前端化模块方案.
那么肯定就不能像没事人那样写以前的那种js代码文件了.

requireJs 提供了一个全局的 define(name?,[dependencies]?,factory)

用来定义一个 AMD 的模块.

其中:

代码格式

define(['moduleA','moduleB','moduleC'],function(moduleA,moduleB,moduleC) {
    // 等待 moduleA , moduleB, moduleC 都加载完毕之后,会进入到这个回调函数.
    
    moduleA.someFn()
    moduleB.someFn()
    moduleC.someFn()
    
    // 这个对象就是当前定义模块返回的API.内容.
    return {
        a: moduleA.xxx,
        b: moduleB.xxx,
        c: moduleC.xxx
    }
})

step 4.编造一个场景,使用rquirejs提供的define()来定义一个模块

regex.js 一个提供正则表达式验证的AMD模块.

define(function () { 
  const phoneRegex = /^(13|14|15|17|18|19)[0-9]{9}$/, // 手机号码(国内)
        emailRegex = /^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}$/ // 邮箱
  
  function isPhoneNum (phone) { 
    return phoneRegex.test(phone)
  }

  function isEmail (email) {
    return emailRegex.test(email)
  }

  // 此模块返回两个函数
  return {
    isPhoneNum,
    isEmail
  }
})

step 5. 使用RequireJS提供的require()来引用regex模块

main.js (入口模块) 使用 regex.js 模块文件.

既然这里使用到的是 requirejs 提供的前端化模块方案.
引用模块需要使用到 requirejs 提供的 require 接口。

RequireJS 提供了一个全局的 require([dependencies],factory)

用来引用一个 AMD 模块(define()定义的)

其中

代码格式

require(['moduleA','moduleB','moduleC'],function(){
    moduleA.someFn()
    moduleB.someFn()
    moduleC.someFn()
})

index.html 导入的

<script src="./js/lib/require.js" async="true" defer data-main="./js/main.js"></script>

main.js 文件中.


require(['./module/regex'], function (regex) { 
  document.getElementById('phone').onblur = function (e) { 
    const value = e.target.value
    let result = regex.isPhoneNum(value) ? '手机号码正确' : '手机号码错误'
    console.log(result)
  }

  document.getElementById('email').onblur = (event) => {
    const value = event.target.value
    let result = regex.isEmail(value) ? '邮箱账号正确' : '邮箱账号错误'
    console.log(result)
  }
})

最后测试结果:

image.png

AMD总结:

<script src="./js/lib/require.js" async="true" defer data-main="./js/main.js"></script>
// AMD 在定义模块时,提倡依赖前置
define(['moduleA','moduleB'],function(moduleA,moduleB){

    // some code here with moduleA...moduleB
})
AMD 在使用模块时,提倡依赖前置
require(['moduleA','moduleB'],function(moduleA,moduleB){
    // some code here with moduleA...moduleB
})

CMD & sea.js

CMD 是 Common Module Definition 的缩写.

它和 AMD 一样,也是用于前端浏览器模块化开发的一个标准.(跑在前端浏览器中的)

国内大神根据此标准创建了 sea.js .

为什么有了AMD之后,还要有一个CMD呢?

AMD & require.js 提倡的是依赖前置.

define(['a','b','c'],function(a,b,c){
    
})

而 CMD 和 AMD 不同之处在于:

CMD 提倡依赖后置,或者说懒加载依赖.只有在使用到某些框架的时候,才去加载依赖.

define(function(require,exports,module){
    const moduleA = require('a')
    if (moduleA.test()) {
        // 只有在需要这个模块的时候,才去加载.
        const moduleB = require('b')
        //.....
    }
})

实现了 CMD 标准的 sea.js 也提供了定义模块使用模块的方法.(模块怎么定义以及怎么使用的)

// math.js
define(function(require,exports,module){
    function add (a, b) {
      return a + b
    }

  module.exports = {
    add
  }
})
// main.js
seajs.use(['./math.js'],function(math){
    math.add(1,2)
})

CMD&sea.js 的基本使用步骤.

step 1.需要下载sea.js源代码

<script src="./sea.3.0.3.js"></script>

和 require.js 不同的是, sea.js 不是指定所谓 data-main 入口js文件.
sea.js 提供一个全局的 seajs.use([dependencies],callback) 接口,用来使用定义的 CMD 模块.

step 2.

创建一个 regex.js 的正则表达式验证模块.

//regex.js

define(function (require, exports, module) {
  const phoneRegex = /^(13|14|15|17|18|19)[0-9]{9}$/, // 手机号码(国内)
    emailRegex = /^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}$/ // 邮箱

  function isPhoneNum(phone) {
    return phoneRegex.test(18571656584)
  }

  function isEmail(email) {
    return emailRegex.test(email)
  }

// 和 commonJS很类似的导出语法.
  module.exports = {
    isPhoneNum,
    isEmail
  }
})

注意:

sea.js 提供的是一个和 commonjs 原理很类似的模块定义方法.(利用闭包函数包裹的方式)

step 3.

创建一个使用此模块的 main.js 文件

// main.js

seajs.use(['./regex.js'], function (regex) {
  window.onload = () => {
    document.getElementById('18571656584').onblur = function (e) {
      const value = e.target.value
      let result = regex.isPhoneNum(value) ? 'CMD-SEAJS-手机号码正确' : 'CMD-SEA-JS手机号码错误'
      console.log(result)
    }
    document.getElementById('email').onblur = (event) => {
      const value = event.target.value
      let result = regex.isEmail(value) ? 'CMD-SEA-JS邮箱账号正确' : 'CMD-SEA-JS邮箱账号错误'
      console.log(result)
    }
  }
})

sea.js 使用全局提供的 seajs.use() 来使用模块.

step 4.

在界面中导入这个js文件.

<script src="./main.js"></script>

step 5.

结果:

image.png

CMD模块使用步骤总结

<script src="./sea.3.0.3.js"></script>
define(function(require,exports,module){
    //..
    
    if (someCondition) {
        // CMD 在导入模块是提倡依赖后置
        const m = require('./someModule.js')
    }
    
    module.exports = {}
})
seajs.use(['a,'b'],function(a,b) {
    //....
})

总结:

上一篇 下一篇

猜你喜欢

热点阅读