您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

ES6+ 模块化(一)

JavaScript 在设计之初主要用来开发 Web 的交互、动画和表单验证等单一的,而且程序的体积很小,大多数都是独立执行的。随着前端的发展 JavaScript 承接的越来越多,Node 的出现让 JavaScript 可以作为一门后端开发语言,程序的复杂度瞬间提升,所以有必要提供一种将 JavaScript 程序拆分为可按需导入的单独模块的机制。Node 是 JavaScript 的先行者,它使用了 CommonJS 的规范来实现模块化的。在 ES6 没出来之前有很多模块化的实践,比较有名的有:CommonJS、AMD、CMD,每个规范都有自己独立的思考。

随着 ES6 模块的发布,AMD 和 CMD 慢慢地淡出了我们的视野。现在主要常见的场景是 Node 端还采用 CommonJS 规范,这是历史原因。前端使用的是 ES6 module 规范,但是不能直接在前端使用,需要通过打包工具进行编译如:Webpack、Babel、Rollup 等。本文中我们将使用 Webpack 进行模块化编译工具,源放在 上,仅供参考。

现在的高级浏览器还能完全地 ES6 的模块化,如何在浏览器中运行 ES6 模块呢?有两种方式:

这两种方式各有优缺点,第一种是原生的使用方式,浏览器兼容要求比较高,第二种使用的是第三方打包编译工具可以很好地浏览器兼容问题,但是会有一定的学习成本,并且不能直接在浏览器中运行,只能使用编译后的。

使用浏览器运行原生 ES6 模块的源码在 的 mjs 中,浏览器是不能直接运行 ES6 模块化的,需一些准备工作。

首先,在引入 js 时需要定义 script 的类型:type="module" 。另外,js 的后缀不能使用 .js 了,需要使用 .mjs 。这样还是不能在浏览器中运行,还需要最后一步。模块化会涉及到系统,而本地打开的 html 是没有服务的,所以我们要使用 node 服务的方式打开 html ,这里我们使用 node 的包 http-server 可以在相应的目录中启动 node 服务。安装如下:

npm install --global http-server

安装完启动服务的工具还是会有问题,依然打不开,这是需要在浏览器中打开一些配置:浏览器地址栏输入:chrome://flags/ 然后 JavaScript 把 Experimental JavaScript 项选择 Enabled 启用状态。如下图。

Webpack 是模块化打包工具,它兼容现在很多模块化加载方式,本节课程也主要使用 Webpack 的方式来学习 ES6 的模块化。Webpack 需要一定的学习成本可以在 上学习,这里就不进行介绍了,下面给出 webpack.con.js 的配置如下:

let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "bundle.js",
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html' // 模版
    })
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },
};

ES6 的模块化设计思想是尽量,使得编译时就能确定模块的依赖关系,只能在顶级作用域。模块系统中,每个都是模块,模块之间都是相互独立。在 ES6 模块中采用 ,不知道的同学可以去看看,对于学习 JavaScript 语言有一定的帮助。

export 是导出语法,import 是导入语法。看下面的实例:

// a.js
export let x = ;
export let y = ;

// main.js
import {x, y} from './a.js';
console.log(x, y)

上面中,a.js 中使用 export 导出 x 和 y 两个变量,在 mian.js 中使用 import 进行导入。a.js 中还可以使用对象的方式导出:

let a = ;
let b = ;
export {
	a,
  b,
}

从上面的 main.js 中可以看出,export 使用的是引用方式进行导出的,导出的是接口,所以不能直接导出值。我们如下实例:

let a = ;
export a;	// 编译报错
// 正确的方式如下
Export let a = ;

虽然使用 export 不能直接导出值,但是可以使用 export default 导出特定的值:

export default ;

export 模块导出的是接口,在模块内如果数据更新,则所依赖的地方的值都是最新的。

// a.js
let a = ;
setInterval(() => {
  a++
})
export {
	a
}

// main.js
import { a } from './a.js';
setInterval(() => {
  consolog.log(a)
})

import 有声明的特点,类似 var 的特点,可以实现变量提升,但是不能变量对应的值。

// main.js
console.log(a)
import { a } from './a.js';
a = ;	// 这样赋值是的

使用 export + from 命令的方式,提供了一种便捷的方式在当前的模块导出其他模块的,不能在当前模块下使用导出的变量。

// b.js
let a = ;
let b = ;
export {
	a,
  b,
}

// a.js
export {a,b} from './b.js';
export c = () => {}
// 等价于使用import 先导入,然后再使用 export 导出
import { a, b } from './b';
export {
	a,
  b,
}

// main.js
import {a, b, c} from './a.js'

export 和 import 命令规定要处于模块顶层,一旦出现在块级作用域内,就会报错。

// a.js
{
	export let a = ;
}

// main.js
{
  import { a } from './a';
}
//控制台答应: 'import' and 'export' may only appear at the top level

上面的中 export 和 import 都放在块级作用域中的,执行时会报错,提升你 export 和 import 只能在顶级出现。

export default 命令用来导出模块中认变量或,上面我们也提到了使用 export 导出的是对象不能导出值类型。

// a.js
export default 'imooc';
// main.js
import name from './a.js'
console.log(name);	// imooc

export default 命令声明的可以是匿名的。

export default function () {
  console.log('imooc');
}
// 等价
function fn() {
  console.log('imooc');
}
export default fn;

也可以是类:

// a.js
export default class {
  constructor() {
    console.log('imooc')
  }
  // ...
}

// main.js
import A from './a';
const a = new A();
console.log(a)

开可以导出的是对象:

const obj = {
  name: 'imooc',
  getLession: function() {
		console.log('ES6 imooc'); 
  }
}
export default obj;

as 命令是用来的,在使用 import 命令导入时可以使用 as 来更改变量名。

// a.js
let a = ;
let b = ;

export {
	a,
  b,
}

// main.js
import { a, b as y } from './a';
console.log(a, y);	// 1,2

如果模块中同时有 export default 导出和 export 导出时,在导入时可以使用 as 对认导出进行。

// a.js
let a = ;
let b = ;

export {
	a,
  b,
}

export default let c = ;


// main.js
import { a, b, default as c } from './a'
// 等价于下面直接在外面进行使用
import c, { a, b } from './a'

认导出的也可以放在 export 导出的对象中,但是需要使用 as default 命令:

// a.js
let a = ;
let b = ;
let c = 'imooc';

export {
	a,
  b,
  c as default,	// 相当于 export default 'imooc',给导出的对象default
}

本节主要讲解了 ES6 Module 的使用,通过对 export、import、default、as 命令的讲解学习了 ES6 Module 的基本,基本上涵盖了日常使用的场景。


联系我
置顶