目錄
存在動態綁定數據
在一個文件中可以使用多個 export 來導出多個模塊
下面以 module.js 文件為例,導出了 arr、str、fun1 模塊
export const arr = [1, 2, 3, 4, 5]; // 導出常量 arr export let str = '字符‘'; // 導出變量 srt export function fun1 (){ console.log('這是導入的函數fun1') } // 導出函數 fun1
當然還有更直觀的寫法
const arr = [1, 2, 3, 4, 5]; let str = '字符‘'; function fun1 (){ console.log('這是導入函數fun1') } // 將要導出的模塊統一寫在一個 export 關鍵字中是很合適的 export { arr, str, fun1 }
存在動態綁定數據的關系,a 變量的改變,可以傳遞到調用者哪里去
export let a = 'a';
setTimeout(()=>{a = 'aa'},1000);
export 導出的變量都是只讀的,因為它的本質是輸入接口,也就是說,不允許在加載模塊的腳本里面,改寫接口
上面使用了 export 導出了模塊,接下來使用 import 導入模塊
import { arr, str, fun1 } from "./module.js";
console.log(arr , str);
fun1();
上面的代碼加載了module.js 文件,並提取了module.js 文件中的 arr、str、fun1 模塊,
module.js 提取模塊的名字需要寫在 {} 中,想要提取什么模塊就寫什么模塊,但是名字必須和 module.js 文件導出時的名字一樣
import也和函數、變量一樣存在預編譯,即可以先使用,后導入
import './module.js'; 如果這么用,相當於加載了一次modules.js 文件,但是並不會導入在modules.js中定義好的模塊或變量
如果是在 html 中的 script 標簽中導出模塊,那么必須為script 標簽添加 script = ' module '
import 不能寫在被其他語句包裹
// 這樣是不可以的 if (x === 1) { import { arr } from './module.js'; } else { import { arr } from './module2.js'; }
使用關鍵字 as 修改模塊名,導出和導入模塊命都可以修改
// A.js文件 const arr = [1, 2, 3, 4, 5]; const str = 'str'; export { arr as numbers, str }; // B.js文件 import {numbers, str as string} from "./module.js"; console.log(numbers, string);
有時候就是想所有模塊都導入,不想把模塊都寫一遍在 {} 中,那么可以 整體加載
// A.js文件 const arr = [1, 2, 3, 4, 5]; const str = 'str'; export {arr, str}; // B.js文件 // 使用 * 號導入所有模塊,然后用 as 重命名,注意這里沒有 {} 了 import * as modules from "./components/2.1as"; console.log(modules.arr, modules.str);
export default(默認導出)
export default 和 export 一樣都是導出模塊,
同樣可以導出 函數、數組、對象、字符串、數值等
但是一個文件中, export 可以有多個,而 export default 只能有一個
export 導出的模塊,導入時要加 {},而export default 導出模塊,導入時不需要 {},但是允許並要求為它重新命名,下例子中取名為 newStr
// A.js文件 let str = 'str'; export default str; // B.js文件 import newStr from './module1';
export 和 export default 可以同時存在一個文件中(但並不建議這么做),導入的時候用 ' , ' 分開。下例子中,一定是 fun 寫在 {arr} 的前面,而不能 將 {arr} 寫在 fun 的前面
// fun 是用 export default 導出的,arr 是用 export,導出的 import fun, {arr} from './module.js';
本質上,export default 導出的是一個 default 的變量/方法,並且 default 后面緊跟的 變量 / 方法 / 值,將會賦值給 default
// 所以下面的寫法都是 正確的
export default function a (){ return 1 } export default () => { return 1 } export default 4 let str1 = '字符'; let str2 = '字符'; export default {str1, str2}
// 而下面的寫法是 錯誤的 export default var a = 'a';
import () (動態引入)
前面說到 import 不能被其他語句包裹,不能動態引入模塊,因為它是在編譯時執行的,不向 require 在運行時才加載,因此可以動態引入
但是 import 函數可以實現動態引入模塊的目的
import 函數返回的是一個 promise 對象
條件加載
if (condition) { import('moduleA').then(...); } else { import('moduleB').then(...); }
按需加載
button.addEventListener('click', event => { import('./dialogBox.js') .then(dialogBox => { dialogBox.open(); }) .catch(error => { /* Error handling */ }) })
動態路徑
import(f())
.then(...);
注意
如果使用 export 導出模塊,那么 import 函數導入模塊后,返回的 promise 對象的值是一個 Module 對象,而這些模塊都是 Module 對象中的屬性,
// A.js文件 export const arr = [1, 2, 3, 4, 5]; export let str = '字符'; // B.js文件 import('./A.js') .then((mod) => { console.log(mod); })
控制台打印如下
所以最好的使用這些模塊的方式,是用對象解構語法
import('./components/1.js') .then(( {arr, str} )=> { console.log(arr, str) })
如果使用 export default 導出,那么使用 import 函數導入后,返回的 promise 對象的值也是一個 Module 對象,與前者的區別在於模塊被賦值到 Module 對象的 default 屬性上
下面圖片中,導出的是 fun1 函數
由於 default 是關鍵字,所以這里就不能直接使用解構了,不過用下面的寫法
// 最簡單的調用屬性 import('./A.js') .then((mod) => { mod.default(); }); // 重命名 import('./A.js') .then(( {default: fun1} )=> { fun1() })
動態引入模塊錯誤
報錯信息有
Module build failed(模塊生成失敗)
Add @babel/plugin-syntax-dynamic-import (https://git.io/vb4Sv) to the 'plugins' section of your Babel config to enable parsing.(將@babel/plugin syntax dynamic import(https://git.io/vb4sv)添加到babel配置的“plugins”部分以啟用解析。)
解決方法
首先安裝 @babel/plugin-syntax-dynamic-import
然后配置 "plugins": ["@babel/plugin-syntax-dynamic-import"]