JS 模組化

2022-09-23 12:00:22

1 AMD 規範介紹

AMD 規範,全稱 Asynchronous Module Definition,非同步模組定義,模組之間的依賴可以被非同步載入。

AMD 規範由 Common JS 規範演進而來,前文介紹 Common JS 規範時說過,瀏覽器端無法直接使用 Common JS,需要使用 browserify 編譯後才能執行。而 AMD 規範規範則專注於瀏覽器端。

1.1 定義模組

AMD 規範定義模組使用 define 函數,函數宣告如下:

define(id?, dependencies?, factory)

引數含義:

- id:非必填,模組的名字。如果沒有傳該引數,模組的名字預設為模組載入器請求的指定指令碼的名字
- dependencies:非必填,陣列,定義的這個模組所需要依賴的模組的陣列。如果定義的這個模組不依賴於其他模組,則不需要傳遞該引數。
- factory:必填,工廠方法。如果為物件,則表示這個模組輸出的值;如果為函數,則是這個模組要乾的事。

如果傳遞了 dependenciesdependencies 中依賴的每項模組會在當前模組的 factory 之前執行。

1.2 載入模組

與 Common JS 規範類似,載入模組使用 require 函數,但 AMD 規範中該函數有兩個引數,語法格式如下:

require([module], callback)

引數含義:

- module:陣列,要載入的模組陣列。
- callback:模組載入成功之後要乾的事。

2 Require JS

require.js 是符合 AMD 規範的 JS 庫,使用 require.js 可以實現 AMD 規範,進行模組的定義和載入。

2.1 使用準備

首先下載 require.js 檔案。require.js 可以從 github 下載。(不知道是不是網路原因,官網我打不開)

在專案中建立 lib 目錄,將 require.js 檔案複製到 lib 目錄中。

2.2 初始化目錄

lib 同級目錄建立目錄 modules,在 modules 目錄中分別建立 module1.jsmodule2.js 代表兩個模組。

同時下載 moment.js 檔案,將其複製到 lib 目錄中。

lib 同級目錄建立入口 HTML 和 JS 檔案,名字分別為:index.htmlindex.js.

此時目錄結構為:

|- 03_AMD/
	|- lib/
		|- require.js
		|- moment.js
	|- modules/
		|- module1.js
		|- module2.js
	|- index.html
	|- index.js

index.html 檔案中通過 script 標籤引入 require.js 檔案,同時指定 data-main 屬性:

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

data-main 屬性指定了在載入完 require.js 屬性後,執行的入口檔案,該檔案也稱為 主模組 。咱們的主模組為 index.html 同級路徑下的 index.js

2.3 路徑設定

在入口 JS 檔案 index.js 中對模組進行設定:

requirejs.config({
  baseUrl: './',
  paths: {
    m1: './modules/module1',
    m2: './modules/module2',
    moment: './lib/moment'
  },
  shim: {
    moment: {
      exports: 'moment'
    },
  }
})
  1. baseUrl 屬性:指定了基本路徑,後面模組路徑設定都是相對於這個基本路徑。
  2. paths 屬性:設定各個模組的名稱及對應檔案路徑(省略 .js 字尾)。上面分別給 module1.jsmodule2.jsmoment.js 三個模組命名為 m1m2moment。名字可以取其他名字,但路徑要正確。
  3. shim 屬性:當使用其他不符合 AMD 規範的模組時,可以使用該屬性匯出模組。(這裡選擇的 moment.js 是相容 AMD 規範的庫,無須設定到 shim 屬性中,此處僅為了簡單演示)

2.4 定義模組

前面建立了兩個自定義模組,現在分別編寫這兩個模組。

module1.js 中定義一個簡單的加法運算:

define(function () {
  console.log('in module1.')

  function sum(num1, num2) {
    console.log('module1 sum function.', num1, num2)
    return num1 + num2
  }

  return {
    sum
  }
})

module2.js 定義一個 calculate 函數,在該函數中需要呼叫 moment.js 中的格式化函數、 module1.js 中的 sum 函數,也就是說該模組(m2)依賴於 moment 模組 和 m1 模組:

define(['m1', 'moment'], function (m1, moment) {

  console.log('in module2.')

  function calculate (n1, n2) {
    console.log('begin calc: ', moment().format('YYYY MMM Do h:mm:ss a'))
    return m1.sum(n1, n2)
  }

  return {
    calculate
  }
})

2.5 使用模組

前面在主模組 index.js 中定義了模組的路徑,現在繼續在該檔案中通過 require 函數使用其他模組:

// ...

require(['m2'], function (m2) {
  const result = m2.calculate(10, 20)
  console.log(result)
})

主模組中載入 m2 模組(module2.js),並呼叫 m2 模組中的 calculate 函數。

2.6 執行

在瀏覽器中執行 index.html,瀏覽器控制檯輸出如下:

image-20220921224121047

主模組(index.js)依賴於 m2 模組(module2.js),m2 模組又依賴於 m1 模組(module1.js),故 require.js 會首先載入 module1.js,輸出 in module1.,然後載入 module2.js, 輸出 in module2.

m1m2moment 三個模組都載入完畢後,才會執行主模組中的 factory 工廠函數。

3 總結

AMD 規範的使用:

  • 定義模組:define 函數
  • 載入模組:require 函數

感謝你閱讀本文,如果本文給了你一點點幫助或者啟發,還請三連支援一下,點贊、關注、收藏,作者會持續與大家分享更多幹貨