听叔一句劝,这里面水太深,历数模块化开发,你把握的住吗?

Posted 贪吃ღ大魔王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了听叔一句劝,这里面水太深,历数模块化开发,你把握的住吗?相关的知识,希望对你有一定的参考价值。


闲言碎语

        持续三天,肝爆了三篇的入门系博文,效果确是那么差强人意,勉强上了热榜,所以今后我还是打算从博文质量下功夫,相比大佬们的一篇一热门,我呢?三篇一热门,但、还是默默选择了肝。正如:深耕于技术写博,致力于前端开发。今后仍是每天一篇有意义的博文,持续更新中…


一、投石问路


1.1 模块化开发起始

这里我先抛出一个问题:什么是模块化开发

相信应该都知道的吧,哪怕知识入门者也会听说过。

那什么叫模块化开发嘞,一个js文件封装的一类内容,多个js文件之间互相配合完成功能。这种开发模式就是模块化开发了。

为什么需要模块化开发?

我从来从这方面来开始分析:

      当我们开发一个功能,需要用到很多函数的时候,会引入工具库文件,它里面会有很多的函数,但是我们在用的时候,却没有使用工具库文件中的所有函数,只是使用了它其中的一部分函数。这样的话就造成了一定的浪费了。

      当然,为了解决不造成浪费这个问题,我们可以将其中操作一类型的函数放在一个单独的文件中,当我们需要进行这一类操作的时候,只引入这一个文件就可以了,就不需要引入它里面的所有函数了。


1.2 起始开发方式


然后这里再聊一下 模块化的发展历史吧

    1995年以后才有了前端这样的代码,最早期的开发者开发 写一个html文件 写css 再写一个js文件 引入一大堆文件。
但是这种开发有最大的弊端 ,一个文件引入十几个css js文件 ,这些文件先引入谁 后引入谁 ,中间有没有覆盖关系 ,其中有没有定义过全局变量 ,定义变量会不会影响原来的文件 , 因为只从两个文件中 到底是谁依赖谁 到底里面定义了哪些东西 我定义的话应该怎么去做 。

大家想 : 我什么也不知道 我以后每次定义变量 需要把每个文件打开 先分析一遍 变量会不会覆盖 有没有被定义。

最早期没有模块化 ,开发者都是一个html引入多个js文件操作,从这点来看 看不出什么优点

缺点呢

  1. 不知道依赖了哪个文件
  2. 第二点是会造成全局变量的污染
  3. 最后就是依赖关系不够清晰

从文件描述中,很难看出来依赖关,每个文件中 全局污染情况不清晰,不知道哪些变量是否该定义,不该定义 。


1.3 IIFE伪模块化规范


⭐      95-2000多年的开发者 比较厉害 打开每个源文件 把里面的文件都看懂以后再写 由于网景: 慢慢有了前端 好多后端工程师跳槽转做前端, 前端好做比较简单,忽然发现前端比较low 连模块化开发都没有,以后看代码还要一个一个打开看 还不如写后端去 他们希望前端具有模块化开发,他们开发了一个 IIFE的伪模块化开发,将js代码放在一个自调用函数中,形成私有作用于,来模拟模块化,(Immediately Invoked Function Expression)的伪模块化规范
Immediately Invoked Function Expression,意为立即调用的函数表达式

使用自调用函数模拟模块,解决部分问题,全局污染问题解决了,但是:

缺点:依赖关系依然不清晰

后端工程师:我尽力了!~

自调用函数

⭐      只要是函数 就会创建作用域 有a变量 再全局的话 暴露容易污染全局 函数定义a 和外面定义a 不会冲突,这就把依赖关系解决的差不多,把全局污染给解决了 但是再今后使用这些文件的时候 还是看不出来谁依赖谁

(function(){
    let a = 10;
    console.log(a);
    function aa(){
        console.log("这是a文件中的aa函数");
    }
    window.a = {
        aa
    }
})()
(function(a){
    let b = 20;
    console.log(b);
    // 需要调用a.js中的aa函数
    // aa()
    a.aa()

    function bb(){
        console.log("这是b文件中的bb函数");
    }

    function bb2(){
        console.log("这是b文件中的bb2函数");
    }

    function bb3(){
        console.log("这是b文件中的bb3函数");
    }
    window.b = {
        bb,
        bb2,
        bb3
    }
})(a)

      再到后面越来越多的人吐槽前端没有模块化开发规范,官方收到这些信息后 认为这些人小题大作,因为官方认为:js就这么一点代码,难道没有模块化开发就不能开发了吗? 他觉得这个东西不需要。


1.4 AMD模块化规范


⭐      后来的话 有一个社区,提倡我们要开发一个模块化规范,它叫做AMD(Asynchronous Module Definition)
由社区发起的模块化标准。但由于不是官方,在js中不能添加关键字,所以写了一个叫做require.js的第三方文件。2011年出现。

这个规范它做了这样一个事儿:

它提供了两个函数

define(function(){
	return 对象
}) // 定义模块

/ 如果定义模块的文件也需要依赖别的文件
define(['依赖的文件路径'],function(自定义的模块名称){
    return 对象
})

require(['引入的文件路径'],function(自定义的模块名称){
    模块名称其实就引入的文件中return的对象
}) // 引入模块

一个叫做 define() 定义模块:
define方法定义独立模块,即不需要依赖其他文件的模块 - 参数是一个函数,需要向外暴露的内容,return出去即可,语法如下:

define(function(){
 需要向外暴露的内容,return出去即可 - 导出内容
 return {
     num,
     f1
 }
})

define方法也可以定义依赖其他模块的模块,语法:

define(['依赖文件1','依赖文件2'...]function(模块1,模块2,...){
 这里就可以使用依赖的模块中的内容了,每个模块变量就是导出的内容
 需要向外暴露的内容,return出去即可
})

一个叫 require() 引入模块:

      require方法,导入其他模块,将导入的文件路径组成一个数组,作为require的参数1,参数2是一个函数,函数中就能使用导入的模块中的内容,函数的参数是模块名称,语法如下:

require(['依赖文件1','依赖文件2'...]function(模块1,模块2,...){
})

这里就可以使用依赖的模块中的内容了,每个模块变量就是导出的内容

define(function(){
    let a = 10;
    console.log(a);
    function aa(){
        console.log("这是a文件中的aa函数");
    }

    for(var i=0;i<=10000;i++){
        console.log(1);
    }

    // return 数据
    return {
        a,
        aa
    }
})
AMD
在这里引入a文件
require(['./18-a'],function(moduleA){
    console.log(789789789789789789);



    console.log("a文件中的变量a是"+moduleA.a);
    console.log('------------');
    console.log("调用a文件中的aa函数:");
    moduleA.aa()
    let b = 20;
    console.log(b);
    function bb(){
        console.log("这是b文件中的bb函数");
    }
    bb()
})

最终,html只需要引入这个文件即可,其他依赖的模块不需要引入

多个文件依赖一个文件,这个文件只会执行一次。

​ 需要向外暴露的内容,return出去即可,在html中只需要引入最后一个即可

这样的话,我用一个js函数就能引入两一个js中定义好的模块,也就解决了什么问题? 让js文件可以引入js文件了

依赖关系变得清晰了 define会定义模块再引入进来

      但是它还是有一个遗憾吧: 它是由这个社区发起的 不是官方啊 所以js中没有给它设置关键字 所以就造成了 我们使用AMD规范 就必须先引入一个叫做 require.js的文件

缺点
      最终引入的这个index文件,它依赖于前面所有的文件,当你引入index文件是 需要先把以前的文件都加载一遍 最后再执行这个index, 这叫做依赖前置 ,这就造成了,我第一次打开页面的时候,好多文件才开始加载,我需要等待很长时间,我的第一屏的屏幕上的页面才展示出来,造成首屏加载特别满,但是后续的操作的话就特别流畅了,因为所有文件已经加载过了。


二、醍醐灌顶


2.1 CMD模块化规范

⭐      后来呢,有一个当时特别nb的人 ,他说你们要开发就好好开发,一群人守在一起开发这样一个有缺点的东西,于是,这个人就开发了CMD

⭐      这个人是谁呢 在以前我们把他叫做 ‘玉伯’ 这是他的艺名 ,他是阿里的工程师,他在以前在IT界呢也是非常厉害 类似于现在大家都知道的 阮一峰 ,廖雪峰这些人的地位 ,经常会写一些博客,发表技术类的东西,以前的这些工程师上网看博客的话都是看玉伯的,玉伯的话就是金科玉律,所以还是很牛批的。
CMD规范 玉伯一个人开发的,由玉伯2011年书写了一个sea.js文件。
当然呢 玉伯也不是官方

使用方式:需要先引入sea.js的文件

通过define方法定义独立模块,语法:

define(function(require,exports,module){
 require用来导入其他模块文件
 module.exports用来导出当前文件中的数据
 exports是modules.exports的引用
})

define方法也可以定义依赖其他模块的模块,语法:

define(function(require,exports,module){
 require用来导入其他模块文件 - 如果有依赖模块,就使用require来导入
 module.exports用来导出当前文件中的数据
 exports是modules.exports的引用
})

通过seajs.use()来导入其他模块文件,语法:

seajs.use(['需要依赖的其他模块文件-可选项'],function(模块名称){

})

这里的依赖模块是可选项,可以有前置依赖,也可以没有

最终只需要引入这一个文件就好了

require用来引入文件 - 实现了按需加载
module.exports 就用来导出数据

define(function(require,exprts,module){
    / exports = module.exports
})

seajs.use(文件,function(模块名称){
    /使用模块中数据
})
define(function(require,exports,module){
    let a = 10;
    console.log(a);
    function aa(){
        console.log("这是a文件中的aa函数");
    }
    // require实现按需加载
    console.log( require('20-test.js').str)
    for(var i=0;i<=10000;i++){
        console.log(1);
    }

    module.exports = {
        a,
        aa
    }
})

CMD

导入a文件

seajs.use('./18-a.js',function(a){
    console.log(789789789);
    a.aa()
})

解决了AMD的依赖前置,可以按需加载

解决了问题:

  1. 依赖前置
  2. 首屏加载很快

问题:后续操作不够流畅,因为CMD标准是什么时候需要,什么时候才加载。

⭐缺点的话,还是没有关键字啊 但是已经很完美了


三、九九归一


⭐⭐在以前的话,模块化开发火到什么程度呢 你只要敢说你是一个工程师,就不敢说自己没听说过CMD

      AMD 和CMD 大概是在11年左右 ,官方后期有了ES6的时候,开发了es6的模块化规范,但是只能在服务器环境使用,也就是http协议使用它,因为初期官方对AMD和CMD的置之不理 ,大家对官方比较失望,虽然它开发出来的es6模块话开发还不错,但是却没有人去用,因为浏览器还是比较牛的,他们并不兼容这个es6模块化规范,所以es6也就一直不愠不火,一直到18年的时候 vue火到不行,vue内置的es6模块化开发,浏览器厂商不得不兼容es6了,谷歌最先兼容了这个es6模块化规范.

3.1 Commonjs


09年的时候呢 nodejs 出来了 nodejs也内置了模块化开发规范:CinnibJS规范 只能在nodejs中使用。


提供了导出和导入的语法:

导入注意:

require(要导入的文件路径)
  1. 导入的路径中, ./ 千万不能省略
  2. 文件的后缀可以省略

导出:

module.exports = {数据}

导出注意

导出的方式

module.exports = {}

module.exports.a = a;

exports.a = a

模块的分类:

1.自定义模块

2.内置的模块 - nodejs自带的

3.内置模块

3.2 es6的模块化


🌙官方后期有了es6的时候,开发了es6的模块化规范 - 只能在服务器环境使用。

特点:

  1. 有了js关键字
  2. 依赖前置
  3. 服务器打开,浏览器支持不好
  4. script标签上添加type=“module”

#在服务器环境中使用es6的模块化规范,首先必须在script标签上添加type属性:

<script type="module"></script>

导出数据:

export default 数据 / 一个文件只能导出这样一个数据
export 定义数据 / 导出多个数据


export default { / 将多个数据组成一个对象,导出一次
    数据 as 别名
}

导入:

import 变量名 from '模块文件路径'
import {解构具体数据} from '模块文件路径'
import * as 变量名 from '模块文件路径';

CSDN技术交流群: 不限萌新大佬,欢迎加入我们的技术圈。

QQ交流群:925570980

微信群:

在这里插入图片描述

博主快肝不动了,喜欢的朋友们可以收藏,一键三连,就是最大的鼓励和支持啊~ 巴适呆板!!

深耕于技术写博,致力于前端开发。

在这里插入图片描述

以上是关于听叔一句劝,这里面水太深,历数模块化开发,你把握的住吗?的主要内容,如果未能解决你的问题,请参考以下文章

听叔一句劝,消息队列的水太深,你把握不住!

听叔一句劝,消息队列的水太深,你把握不住!

《面试技巧》孩子,听叔一句劝,面试水太深,你把握不住。

《面试技巧》孩子,听叔一句劝,面试水太深,你把握不住。

《面试技巧》孩子,听叔一句劝,面试水太深,你把握不住。

MySQL 中的一些坑