VueMastery

每个人编写的模块
通过 script
标签引入到页面
中,然后就可以使用模块
中的内容了。
随着 nodejs
的诞生,为了解决在 nodejs
中的模块化问题,社区自发形成了很多的模块化方案,其中 CommonJS
模块化规范得到了时间的检验,并最终确定为主流的模块化规范,这是一套社区的模块化规范,使用 commonjs
规范编写的模块并不能直接在浏览器中运行。后来出现了browserify
,webpack
等编译、打包工具,使得 CommonJS
模块化规范编写的代码经过编译、打包后也可以用于浏览器中运行。
// 1. 使用 exports 导出模块
exports.add = (a, b) => a + b
// 2. 使用 module.exports 导出模块
module.exports = {
add,
}
const utils = require('./utils')
// 或者加后缀
// const utils = require('./utils.js')
// 也可以解构方式导入
// const { add } = require('./utils.js')
const result = utils.add(1, 2)
注意事项:
this
、exports
、module.exports
在初始时,都指向同一个空对象,这个空对象就是当前模块导出的数据。module.exports
为准。exports
是对 module.exports
的引用,仅为了方便给导出对象添加属性,所以不能使用exports = value
的形式导出数据,但是可以使用module.exports = value
的形式导出数据。commonjs
模块化规范中,实际是通过内置函数
来实现模块化的,我们可以通过arguments.callee.toString()
获取当前模块的代码,从以下的代码我们可以看出,一个 JS 模块在执行时,是被包裹在一个内置函数
中执行的,所以每个模块都有自己的作用域。// utils.js
function (exports, require, module, __filename, __dirname) {
exports.add = (a, b) => {
return a + b
}
exports.sub = (a, b) => {
return a - b
}
console.log(arguments.callee.toString())
}
说明:
ES6
模块化规范是ECMA
官方标准的规范,它是在语言标准的层面上实现了模块化功能,是目前最流行的模块化规范,且浏览器与服务器均支持该规范。
ES6
模块化规范的导入导出方式: export
分别导出语法export const add = (a, b) => a + b
export
统一导出语法const sub = (a, b) => a - b
const mul = (a, b) => a * b
export { sub, mul }
export default
默认导出语法export default (a, b) => a + b
export { mul as alias }
在统一导出方式中取别名export { mul as alias }
import * as alias
统一导入语法(通用)import * as utils from './utils.js'
import { mul as multi } from './utils.js'
import utils from './utils.js'
async function main() {
const utils = await import('./utils.js')
console.log(utils)
}
main()
import
可以不接受任何数据import './utils.js'
提示:
通过模块化解决了:(1)全局污染问题 (2)依赖混乱问题 (3)数据安全问题
const add = (a, b) => a + b
const sub = (a, b) => a - b
const mul = (a, b) => a * b
// 分别导出
// export const greet = (name) => `hello ${name}` // 错误演示
// 不能既分别导出又统一导出,否则会报 SyntaxError: Duplicate export of 'greet'
// 统一导出
export {
add,
// 使用 as 给导出模块取别名,取的别名如果是 default, 则该模块会等价 export default 默认导出
mul as default,
mul,
sub, // greet
}
import mul, { add, mul as multi, sub } from './utils.js'
// 如果需要默认导入和按需导入在同一行,则默认导入需要写在最前面
console.log(add, sub, mul, multi)
注意事项:
分别导出
,则不能使用统一导出
,否则会报 SyntaxError: Duplicate export of 'greet'
。这两种导出本质是都是同一种方式。import
导入模块时,如果需要默认导入和按需导入在同一行,则默认导入需要写在最前面。as
关键字给变量名取别名。ES6
模块化规范的代码,第一种方式可以在项目的package.json
文件中添加"type": "module"
,第二种方式可以在文件名后添加.mjs
后缀,表示该模块是ES6
模块化规范的模块。说明:
AMD
是Asynchronous Module Definition
的缩写,即异步模块定义
。它是一种模块化规范,主要用于浏览器端。该模块化规范需要依赖require.js
库,所以需要先引入require.js
库,然后才能使用AMD
模块化规范。
require.js
库在
require.js
库中,define
函数用于定义模块,require
函数用于导入模块。在引入require.js
库后,需要在script
标签上指定模块的入口文件data-main
属性,该属性值为模块的入口文件路径。
<script data-main="./main.js" src="https://cdn.bootcdn.net/ajax/libs/require.js/2.3.7/require.min.js"></script>
main.js
文件中编写配置,注册模块/** AMD 模块化的入口文件,要编写配置对象,并且有固定写法 */
requirejs.config({
// 基本路径
baseUrl: './js',
// 模块表示名 与 模块路径的映射关系
paths: {
utils: 'utils',
math: 'math',
},
})
/** AMD 使用 require 函数的第一个参数表示依赖模块,
* 第二个参数表示回调函数,回调函数中的参数表示依赖模块的导出结果,会按照依赖顺序将模块对象依次传入到对应形参上
*/
require(['utils', 'math'], function (utils, math) {
console.log(utils)
console.log(math)
const r1 = utils.getTime()
const r2 = math.add(1, 2)
console.log('当前时间:', r1, '\n1 + 2 = ', r2)
})
// ./js/math.js
const add = (a, b) => a + b
const sub = (a, b) => a - b
define(function () {
return {
add,
sub,
}
})
// ./js/utils.js
function getTime() {
const t = new Date()
const hours = t.getHours()
const minutes = t.getMinutes()
const seconds = t.getSeconds()
return `${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)}`
}
function padZero(n) {
return n.toString().padStart(2, '0')
}
// AMD 使用 define 函数定义模块
define(function () {
return {
getTime,
padZero,
}
})