在轉寫框架時,用了很多import
,可是卻不知道有區分靜態跟動態導入(dynamic import)?那動態載入跟框架裡面的用法有什麼關係?
於是我將很多困惑交給最強顧問chatGPT 4.0,因此有了以下整理:
目錄
- JavaScript模組系統的歷史背景
- ES模組(ECMAScript Modules)的import語法
- 如何區分該用什麼模式導入?
- 動態導入在不同框架中使用方式
- Vue3中的defineAsyncComponent跟import()有什麼差別?
<script>
於標籤中。這樣做會導致全局作用域污染和命名衝突。<script src="script.js"></script>
// javascript
(function() {
// 模組程式碼
})();
CommonJS 和 AMD
Node.js 採用了CommonJS作為其模組系統,這也影響了前端開發。CommonJS 使用 require()
和 module.exports
來導入和導出模組。
AMD(Asynchronous Module Definition)則是另一種模組定義標準,主要用於瀏覽器,它支持非同步加載。
UMD(Universal Module Definition)
UMD是一種嘗試統一CommonJS和AMD的模組定義方式。
ECMAScript Modules(ESM)
ECMAScript 2015(也稱為ES6)引入了原生的模組系統。這是第一次JavaScript有了原生的模組支持。ESM使用import
和export
語句來導入和導出
模組。
如果想知道寫法差異,可看此篇
延伸閱讀:
實現AMD的require.js 與 ES6 Import/Export 大比拚
分為靜態導入(Static Import)以及動態導入(Dynamic Import)
import ... from ...
語法)啟動時
就將所有模組加載進來基本用法:
import * as myModule from "/modules/my-module.js"; //導入整個模組
import { foo, bar } from "/modules/my-module.js";//導入特定的功能或變數
import { add as addition } from '/modules/my-module.js';//導入並重新命名
import myDefault from "/modules/my-module.js";//導入默認值,引入模塊有一個default export
...等多種寫法
小提醒:
如果是你在HTML引用靜態導入,要加上<script type="module">import ... from ... ;</script>
前往 >> 小試身手
import()
函式)基本用法:
當使用者點擊到才會調用模組的方法,進而做後續處理
const main = document.querySelector("main");
for (const link of document.querySelectorAll("nav > a")) {
link.addEventListener("click", (e) => {
e.preventDefault();
import("/modules/my-module.js") // 動態導入
.then((module) => {
// 使用module做一些事情
module.loadPageInto(main);
})
.catch((err) => {
// 處理錯誤
main.textContent = err.message;
});
});
}
Promise
,當模組載入完成後,這個 Promise 會解析(resolve)為該模組的導出(exports),所以也可以支持 await
寫法詳細可看
MDN介紹import
/ | 用途 |
---|---|
靜態導入 | 用於基本依賴和全局模組,它在編譯時解析。 |
動態導入 | 用於需要條件加載或懶加載的模組,它在運行時解析。 |
import React from 'react'; // 基本依賴
import { add } from './math'; // 自定義模組
簡單來說像是基本的vue,或者組件內使用的套件不太可能是需要動態才載的
// 條件加載
if (userIsAdmin) {
import('./adminModule.js').then(module => module.init());
}
// 懶加載和代碼拆分
button.addEventListener('click', () => {
import('./dialogBox.js').then(module => module.open());
});
簡單來說可以根據某些條件來決定是否導入某個模組或者你的應用程式非常大時需要按需加載
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const routes: Routes = [
{ path: 'lazy', loadChildren: () => import('./lazy.module').then(m => m.LazyModule) }
];
const routes = [
{
path: '/dynamic',
component: () => import('./DynamicRouteComponent.vue'),
},
];
...當然還有其他出現的場景
若你想知道針對vue路由動態載入跟靜態載入網頁跑起來有什麼差別,可以看
延伸閱讀:
不只懂 Vue 語法:為何懶加載路由和元件會提升網頁效能?
還記得我們在17篇已經介紹過defineAsyncComponent,當時我的需求是,當使用者點擊按鈕打開下面視窗才要載入元件的資源,
以下為範例代碼
<template>
<div>
<button @click="show = !show">點我打開視窗</button>
<dynamicModel v-if="show" />
</div>
</template>
<script setup>
import { ref,defineAsyncComponent} from 'vue';
const dynamicModel = defineAsyncComponent(() => import('./dynamicModel.vue')); // 動態載入组件
const show = ref(false);
</script>
但是其實寫成
<template>
// 同上
</template>
<script>
import { ref } from 'vue';
export default {
components: {
dynamicModel: () => import('./dynamicModel.vue')
},
setup() {
const show = ref(false);
return {
show,
};
},
};
</script>
成果都為下,所以我想知道這兩個差異?
(一開始沒載入dynamicModel,打開後才載入)
前往 >> Demo 網址:https://hahasister-ironman-project.netlify.app/#/asyncComponent
而差異是,
import():它是JavaScript的內置功能,用於在運行時動態加載模塊,可以用於任何JavaScript模塊,包括Vue組件。這是異步加載的一種方式,可以實現僅在需要時才加載組件。
defineAsyncComponent():它是Vue 3提供的工具,主要用於定義Vue組件的異步加載方式,且有多種參數可以設定。它簡化了在Vue應用程序中使用import() 動態載入組件的過程,但實質上它使用的還是import()來實現異步加載。
兩者都可以實現異步加載,只是defineAsyncComponent() 提供了一種Vue內置的方式,讓您更容易地在Vue組件中使用import() 進行異步加載。
以上希望大家有一起解到困惑,讓今晚有個好眠
那我們明天再見~