前端模块发规范及进化史

前言

最开始的模块化开发:把每个模块代码写在不同的文件中,最后在页面中分别导入

  • 需要自己分析出相关的依赖,规划出导入的先后顺序(麻烦)即使基于geunt/gulp/webpack等打包工具,也需要知道依赖关系,按照依赖顺序打包'
  • 如果不基于闭包把每一个模块私有化处理,最后合并在一起的时候,容易引发全局变量污染,

所有设计模式都是一种思想,这种思想解决了某些问题

单例设计模式

解决私有化: 自执行函数,产生闭包

解决模块之间的相互访问:把需要供外面访问的内容,暴露到全局上windowxxx=xxx,使用这种方式需要暴露更多的方法的时候,也可能会导致变量全局冲突

把模块中需要暴露的属性和方法,放在一个对象中管理,最后基于模块名存储这个对象即可

let xModule=(function(){
...
return{
//包含里需要暴露给外面的属性和方法
fn,
}
})()

访问:xModule.fn()

总结:这种处理方案,即保证了代码的私有化,也支持了模块间的相互访问,而且避免了全局变量的污染..我们把这种代码的设计方法称之为"单例设计模式"

AMD按需导入

AMD模块化思想 - require.js,导入;require , define:定义模块

 网址:RequireJS

 AMD设计思想:在单例设计模式基础上,有效的解决了模块之间的依赖问题,告别之前“手动一点点分析依赖,按照顺序依次导入”的问题了;而且可以结合gulp/grunt等,最后把各个模块代码合并压缩打包在一起... , 但是依赖的模块都需要“前置导入”

用法

入口:mian.js

//全局配置
require.config({
   baseUrl: 'js/lib',
});
// 导入指定模块,然后处理相关的内容
require(['B', 'A'], function (B, A) {
    console.log(A.sum(10, 20, 30, 40, 50));
    console.log(B.average(10, 20, 30, 40, 50));
});

模块中

  • // define:定义模块
  • // AMD思想的优势:定义模块的时候,可以把依赖的模块“前置导入”
  • // 回调函数中基于AModule接收导入的A模块内容(A模块中返回的对象)
define(['A'], function (AModule) {
    let name = "lisa";
    const average = function average(...params) {
        let len = params.length,
            total = AModule.sum(...params);
        if (len === 0) return 0;
        return (total / len).toFixed(2);
    };

    return {
        average
    };
});

 CommonJS模块规范

 CommonJS模块规范「模块的导入和导出」:Node自带的模块规范(浏览器端不支持)

 定义模块:创建的每一个JS文件,就是定义一个单独的模块,每个模块之间的代码本身就是私有的

导入:require 导出 module.exports 

 导出模块中的方法:

 module.exports = {
          //包含需要供外部调用的属性和方法
      };

导入指定的模块:

     const x = require('模块地址,导入自己的模块需要加“./”');
      基于x接收导出的对象,后期基于 x.xxx 即可访问!!

 CommonJS模块的导入是“按需”的,随时用随时导入即可,不像AMD都需要前置处理!!,比AMD用起来跟简单,性能好一些

CMD

 CommonJS不支持浏览器,所以淘宝玉伯写了一个插件 sea.js(把其定义为cmd模块规范)

本质把 CommonJS规范搬到浏览器运行

es6Module,出现以后sea代表的CMD被pass掉了

es6模块规范

  在浏览器端开启ES6Module规范

  •        + type="module"
  •        + 基于标准的http/https协议的web服务预览页面

 定义模块:和CommonJS类似,创建一个JS就相当于创建一个模块

 导出/导入模块:

导出

  • export 声明变量且赋值;
  • export default 值;  -> 在一个模块中只能使用一次 ,每个模块导出一个Module对象

导入: import x from '模块地址'

  • -> 浏览器端直接使用,地址中模块的后缀不能省略
  • -> 只能接收到基于 export default 导出的这个值
  • -> 原理:找到导出Module对象中的default属性值,把属性值赋值给x变量
  •  -> 但是不能在这直接给x解构赋值 ,例如:import {n,m} from '模块地址';  这样是不能给default后面的值解构赋值;需要解构赋值,则先基于x接收,然后再给x解构赋值即可;例如:const {n,m}=x;

导入: import * as x from '模块地址';

  • 把当前模块导出的所有内容获取到,赋值给x变量,后期基于 x.xxx 访问即可「含: x.default 获取export default导出的值」

导入: import { num, obj } from '模块地址';

  •  直接结构赋值,是把模块导出的Module中所有内容(不含default)进行解构赋值

注意:

  •  import需要放在模块代码的最上面编写,有点类似于前置导入
  •  export default 只能导出一个(Module对象),import导入时会找到导出Module对象中的default属性值,把属性值赋值给x变量
  •  export 可以导出多次 ,可以结构赋值拿到,或者import * as x from '模块地址';,导出全部赋值给x

总结

单例设计模式是“最早期的模块规范”,在没有CommonJS/ES6Module模块规范的时代,帮助我们实现了模块化开发!AMD(require.js)是在单例设计模式的基础上,实现了模块和模块之间的依赖管理!-----但是上述操作都是过去时了

当代前端开发,都是基于模块化进行开发,而模块化方案以 CommonJS/ES6Module 为主

  •   + 他们都是按照创建一个JS就是创建一个模块来管理的「每个JS文件中的代码都是私有的」
  •    + CommonJS:require && module.exports
  •    + ES6Module:export && import 

我们编写的JS代码,可以运行的环境

  • @1 浏览器  <script src='...'> 「和其类似的还有webview」:直接支持ES6Module,但是不支持CommonJS    全局对象 window
  •  @2 NODE   支持CommonJS,但是不支持ES6Module,  全局对象 global
  •   @3 webpack「基于node实现代码的合并压缩打包、最后把打包的结果导入到浏览器中运行」 CommonJS&ES6Module都支持,而且支持相互之间的“混用”(原理:webpack把两种模块规范都实现了一遍)  支持 window&global
  •   @4 vite「新的工程化打包工具」+ 不是像webpack一样编译打包的,它本质就是基于ES6Module规范,实现模块之间的相互引用
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值