🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 模块化 ### import [[MDN文档,import](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import)] #### 静态`import` **`import`** 语句用于导入由另一个模块导出的绑定。无论是否声明了 [`strict mode`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode "如果你想改变你的代码,让其工作在具有限制性JavaScript环境中,请参阅转换成严格模式。"),导入的模块都运行在严格模式下。 在浏览器中,`import`语句只能在声明了`type="module"`的`script`的标签中使用。 静态的`import`是初始化加载的最优选择,使用静态`import`更容易从代码静态分析工具和[tree shaking](https://developer.mozilla.org/zh-CN/docs/Glossary/Tree_shaking)中受益。 语法 ~~~js // 直接导入默认值,在`default export`有效时可用。 import defaultExport from "module-name"; //导入默认值??,在`default export`有效时可用。 import defaultExport, { export [ , [...] ] } from "module-name"; // 导入整个模块的内容(导入所有导出) import * as name from "module-name"; // 导入单个导出 import { export } from "module-name"; // 导入时重命名(带有别名)的导出 import { export as alias } from "module-name"; // 导入多个导出,导出文件与导入文件在同一个目录里 import { export1 , export2 } from "module-name"; // 导入多个导出,导出文件与导入文件不在同一个目录 import { foo , bar } from "module-name/path/to/specific/un-exported/file"; // 导入时重命名多个导出 import { export1 , export2 as alias2 , [...] } from "module-name"; // myModule used as a namespace,在这种情况下,`default`导入必须首先声明 import defaultExport, * as myModule from "module-name"; // 仅为副作用而导入一个模块,这将运行模块中的全局代码, 但实际上不导入任何值。 import "module-name"; ~~~ * **`defaultExport`** 将引用模块默认导出的名称。 * **`module-name`** 要导入的模块。这通常是包含模块的`.js`文件的相对或绝对路径名,不包括`.js`扩展名。某些打包工具可以允许或要求使用该扩展;检查你的运行环境。只允许单引号和双引号的字符串。 * **`name`** 引用时将用作一种命名空间的模块对象的名称。 * **`export, exportN`** 要导入的导出名称。 * **`alias, aliasN`** 将引用指定的导入的名称。 #### 动态`import()` 希望按照一定的条件或者按需加载模块的时候,动态`import()`是非常有用的。它不需要依赖`type="module"`的script标签。 语法 ~~~js var promise = import("module-name"); ~~~ 可以将关键字`import`称作动态导入模块的函数,当使用它的时候,会返回一个`promise`。 `import()`加载模块成功以后,这个模块会作为一个对象,当作`then`方法的参数。因此,可以使用对象解构赋值的语法,获取输出接口。 ~~~js import('/modules/my-module.js') .then((module) => { // Do something with the module. }); ~~~ ~~~js //获取导入的myModule.js(命名输出接口)输出接口,方法1 import('./myModule.js') .then(({export1,export2})=>{ // ... }); //获取导入的myModule.js(default输出接口)输出接口,方法2, import('./myModule.js') .then(myModule=>{ console.log(myModule.default); }); //获取导入的myModule.js(default输出接口)输出接口,方法3,将default具名输入 import('./myModule.js') .then(({default:theDefault})=>{ console.log(theDefault); }); //同时加载多个模块 Promise.all([ import('./module1.js'), import('./module2.js'), import('./module3.js'), ]) .then(([module1,module2,module3])=>{ ··· }); ~~~ 这种使用方式也支持`await`关键字。 ~~~js let module = await import('/modules/my-module.js'); ~~~ `import()`也可以用在 async 函数之中。 ~~~js async function main(){ const myModule=await import('./myModule.js'); const {export1,export2}=await import('./myModule.js'); const [module1,module2,module3]= await Promise.all([ import('./module1.js'), import('./module2.js'), import('./module3.js'), ]); } main(); ~~~ #### 示例 * 标准导入 ~~~js //file.js function getJSON(url, callback) { let xhr = new XMLHttpRequest(); xhr.onload = function () { callback(this.responseText) }; xhr.open('GET', url, true); xhr.send(); } export function getUsefulContents(url, callback) { getJSON(url, data => callback(JSON.parse(data))); } ~~~ 从辅助模块file.js导入以协助处理AJAX JSON请求。 ~~~js //main.js import { getUsefulContents } from '/modules/file.js'; getUsefulContents('http://www.example.com', data => { doSomethingUseful(data); }); ~~~ * 动态导入 ~~~js 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.loadPageInto(main); }) .catch(err => { main.textContent = err.message; }); }); } ~~~ 上例中,通过点击按钮,触发动态`import()`去加载函数,然后执行。当然这不是唯一的方式,`import()`函数也可以支持`await`。 ### export [[MDN文档,export](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/export)] `export`语句用于在创建JavaScript模块时,从模块中导出函数、对象或原始值,以便其他程序可以通过`import`语句用于导入由另一个模块导出的绑定。无论是否声明了 strict mode ,导入的模块都运行在严格模式下。 >[warning] 此特性目前仅在 Safari 和 Chrome 原生实现。它在许多转换器中实现,如[Traceur Compiler](https://github.com/google/traceur-compiler),[Babel](http://babeljs.io/)或[Rollup](https://github.com/rollup/rollup)。 ~~~js // 命名导出 export { name1, name2, …, nameN }; export { variable1 as name1, variable2 as name2, …, nameN }; export let name1, name2, …, nameN; // also var export let name1 = …, name2 = …, …, nameN; // also var, const // 默认导出(函数) export function FunctionName() {...} // 默认导出(类) export class ClassName {...} export default expression; export default function (…) { … } // also class, function* export default function name1(…) { … } // also class, function* export { name1 as default, … }; export * from …; export { name1, name2, …, nameN } from …; export { import1 as name1, import2 as name2, …, nameN } from …; ~~~ * **`nameN`** 导出的标识符(用来被其他脚本的`import`导入) #### 使用命名导出 在模块中,我们可以使用以下代码: ~~~js // module "my-module.js" function cube(x) { return x * x * x; } const foo = Math.PI + Math.SQRT2; export { cube,foo }; ~~~ 这样的话,在其它脚本我们可以这样使用: ~~~js import { cube, foo } from 'my-module.js'; console.log(cube(3)); // 27 console.log(foo); // 4.555806215962888 ~~~ #### 使用默认导出 1. 如果我们要导出一个值或模块中的返回值,就可以使用默认导出: ~~~js // module "my-module.js" export default function cube(x) { return x * x * x; } ~~~ 然后,在另一个脚本中,可以直接导入默认导出: ~~~js // module "my-module.js" import cube from 'my-module'; console.log(cube(3)); // 27​​​​​ ~~~ >[warning] 注意,不能使用`var`,`let`或`const`用于导出默认值`export default`。 2. 直接导出 ~~~js // conf.js export default { a:'11'; b:{m:'22',n:[]}; c:function(){} }; ~~~ ~~~js //main.js,conf.js与main.js在同一目录内 import conf from './conf.js' console.log(conf.a); ~~~ #### 模块重定向 如果我们要从另一个模块(有效地创建“重定向”)中导出默认值(default)和 星标(\*): ~~~js // module "redirect-module.js" export {default} from './other-module'; export * from './other-module'; ~~~ ## 深入理解module 1. [ES6 in Depth: Modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/), Hacks blog post by Jason Orendorff 2. [Axel Rauschmayer's book: "Exploring JS: Modules"](http://exploringjs.com/es6/ch_modules.html) 3. [export、exports、modules.exports 和 require 、import 的一些组合套路和坑](https://www.cnblogs.com/CyLee/p/5836069.html) 4. [Node中没搞明白require和import,你会被坑的很惨](https://imweb.io/topic/582293894067ce9726778be9?utm_source=tuicool&utm_medium=referral) 5. [javascript 中的require /exports 和import/export](https://blog.csdn.net/qq_37755555/article/details/78688525) 6. [Es6中的模块化Module,导入(import)导出(export)](https://mp.weixin.qq.com/s/NDA46vKoFuZt09Qx8SNf6Q)