妈妈!妈妈!🤖什么是前端模块化哇!

108 阅读4分钟

前端模块化

认识模块化

什么是前端模块化?

  • 模块化的开发方式可以提高代码复用率,方便进行代码的管理。通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数。

模块化演变过程

阶段一:文件划分

//model_1.js
//将每一个功能单独放置在一个js文件中,通过script引入使用

val msg1 = '阶段一:文件划分'

//弊端:全局污染

阶段二:命名空间

//model_2.js
//在第一阶段的基础上面,将每一个模块内部的内容统一放置到一个变量下面

var Model_2 = {
    msg2:'阶段二:命名空间'
}

//弊端:仍然没有私有空间,依然可以被外部访问修改

阶段三:立即执行函数包裹

//model_3.js
//使用立即执行函数进行包裹,利用函数作用域,使其具有私有空间(私有成员)

(function(){
    var msg3 = '阶段三:立即执行函数'//私有变量
    function fn3 (){
        console.log(msg3)
    }

    window.modele3 = {
        fn3:fn3//挂载暴露函数
    }
}())

上述方法外部调用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="前端模块化演变过程" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script src="阶段一_文件划分.js"></script>
<script src="阶段二_命名空间.js"></script>
<script src="阶段三_立即执行函数包裹.js"></script>
<script>
    console.log(msg1)
    console.log(Model_2.msg2)
    window.modele3.fn3()
</script>
<body>
    
</body>
</html>

8D)_Z~0U9PSG_Z3@7G{H)R5.png

上述方法弊端:维护困难

模块化规范探索

CommonJS规范

Node.js是commonJS规范的主要实践者

弊端:因为CommonJS是同步加载的,不适用于浏览器

AMD

异步模块定义规范

弊端:使用起来相对复杂

CMD

弊端:使用起来相对复杂,与AMD类似

模块化规范探索-传送门

模块化标准规范 ES-Modules

ES Modules 特性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="ES Models" content="width=device-width, initial-scale=1.0">
    <title>ESMt特性</title>
</head>
<body>
    <h2>ESMt特性</h2>
    <ul>
        <li>特性一:自动采用严格模式,忽略'use strict'</li>
        <li>特性二:每个ESM模块都是单独的私有作用域</li>
        <li>特性三:ESM是通过CORS去请求外部JS模块的</li>
        <li>特性四:ESM的script标签会延迟执行脚本,页面渲染完成后再加载</li>
    </ul>
    <script type="module">
        //原生html中通过给script添加 type="module" 指定其为ESM模块
    </script>
</body>
</html>

导入导出

导出

//app.js
//--------------------------------------------1
export var msg1 = '分别导出变量'
export var fn1 = function () {
    return '分别导出方法'
}

//--------------------------------------------2
var msg2 = '统一导出变量'
var fn2 = function () {
    return '统一导出方法'
}

//--------------------------------------------3
var msg3 = '统一导出变量,并重命名'
var fn3 = function () {
    return '统一导出变量,并使用关键字default指定其为默认导出'
}

//--------------------------------------------4
//统一在末尾导出
export {
    msg2,//统一导出变量
    fn2,//统一导出方法
    msg3 as Tmsg3,//统一导出变量,并重命名 --使用as重命名
    fn3 as default//使用关键字default指定其为默认导出(被指定默认导出的变量接收时必须重命名)
}

//--------------------------------------------5
//export default fn3//使用export default默认(统一)导出

导入

//index.js
//----------------------------------------------------1
//分别导入
import {
    msg1,
    fn1,
    msg2,
    fn2,
    Tmsg3 as TTmsg3,//使用as重命名
    default as Dfn3//默认导出,分别导入时必须重命名
} from "./app.js";

//----------------------------------------------------2
//统一(默认)导入
import app from "./app.js"

//----------------------------------------------------3
//使用*导出所有成员
import * from './app.js'

//----------------------------------------------------4
//使用*获取导出的全部成员,并重命名接收
import * as Mapp from './app.js'

//----------------------------------------------------5
//只执行模块,而不导入其内容的写法
import {} from "./app.js"//方法一:空{}
import "./app.js"//方法二:只使用import

//----------------------------------------------------6
//动态加载-异步加载
import('./app.js')
//其是Promise风格
import('./app.js').then(M=>{
    console.log(M)//其返回模块
})

//----------------------------------------------------7
//混合导入:同时获取分别默认暴露和分别(具名)暴露
import app,{msg1,fn1} from './app.js'//,号前获取默认暴露(导出),,后获取分别暴露

注意

导入导出中的{}
var msg = 'msg-app-2'

//分别暴露(导出)中的{}并非对象,其内部变量也不是对象字面量简写,这只是导出特有的写法
export {
    msg
}

//统一暴露 其后{}则是一个对象
export default {
    msg
}
//导入时的{}也并非解构,只是导入的特定写法
import {msg} from "./app2.js"
只读性
 //导出时实际是对内存的引用,而非对对象的拷贝
 //另外,导入的内容是只读的,不可修改
 import {msg} from "./app2.js"
导入的完整性
//导入完整性
//导入必须是完整路径,项目中可省略是因为在打包工具中进行了处理

import {msg1} from "./app"//完整性一:不能省略后缀
import {msg2} from "app.js"//完整性二:相对路径中./不可省略,如果省略则可能会被误认为在加载第三方模块
import {msg3} from "/a1"//完整性三:如果要加载a1文件夹下的index.js文件,index.js不可省略
导入后立马导出
//导入后立马导出
export {msg1,fn1} from './app.js' //这样在本文件中无法使用其成员

浏览器兼容

。。。。。。

Polyfill:一个Js兼容适应的小玩具(补丁),闻一闻

nodeJs中使用ES-Modules

node8.5过后可以在nodeJs中实验性使用ES-Modules