当前位置: 首页 > Web前端 > vue.js

前端模块化

时间:2023-03-31 22:37:49 vue.js

1.什么是模块化?!--/TOC-->1。什么是模块化?模块化并不是前端独有的想法。模块化是一个自上而下的过程。通过将一个大系统逐渐划分成小的模块,这些模块在内部封装一些特定的功能,并通过约定的接口对外暴露。各模块互不干扰,插拔方便。模块化可以解耦代码并更好地重用它。各个模块互不影响,不用担心变量污染、命名冲突等问题,也有利于并行开发,提高效率。js本来就不是模块化的。随着前端应用越来越复杂,比如一个html页面请求多个js文件时,如何保证这些js文件之间的变量互不干扰?为了解决变量污染、命名冲突等问题,js开始有了一些模块化的解决方案,从2003年提出的闭包模块化,到2009年的CommonJS和AMD,再到今天的ES模块化。2.为什么需要模块化模块化的好处可以概括为:拥有独立的作用域,避免变量污染,命名冲突,降低项目复杂度,提高开发效率,提高代码的复用性和可维护性3.在源代码中模块化中上面提到的AMD和Commonjs规范,对模块化的定义是不同的,在进行模块化的时候需要兼容不同的环境。3.1AMDAMD(AsynchronousModuleDefinition),异步模块定义。在加载模块和模块所依赖的其他模块时,AMD采用异步加载的方式来避免模块加载阻塞网页渲染。作为一个规范,AMD只需要定义它的语法API,而不关心它的实现。AMD的规范很简单,只有一个API,就是模块定义了define函数:define(name?,[dependencies]?,factory)name是模块的标识,如果不提供,则为由文件名标识;dependencies表示它所依赖的模块;factory是模块初始化时要执行的函数或对象。如果它是一个函数,它只会被执行一次。如果它是一个对象,它将是模块的输出值。AMD规范主要是针对前端浏览器的规范。3.2CommonjsCommonJS规范规定,在每个模块内,模块变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是一个外部接口。加载模块实际上是加载模块的module.exports属性。CommonJS规范的加载模块是同步加载的,也就是说加载完成后才能进行后面的操作。模块定义语法:module.exports=factory()CommonJS主要是针对浏览器以外的js环境的规范。3.3Vue源码解析模块化以vue2源码为例。折叠源码后,你会看到如下代码:这是一个匿名自执行函数。这个匿名函数有一个独立的作用域,既避免了污染外部代码,又避免了被外部代码污染。如果需要使用外部全局变量,可以传入参数,如图中这样。这实际上是一个Window对象。通过传入这个,Window从全局变量变为局部变量。当下面的代码块中访问this时,不需要将作用域链回滚到顶级作用域,这样可以更快地访问Window对象;将Window作为参数传递也可以在压缩代码时进行优化。如:(function(a,b){})(window);//窗口优化为a.global就是执行时传入的this参数,也就是Window对象。factory是传入的第二个参数,也就是后面的匿名函数。展开第一个函数可以看到如下代码:typeofexports==='object'&&typeofmodule!=='undefined'?module.exports=factory():typeofdefine==='function'&&define.amd?定义(工厂):(全球=全球||自我,全球.Vue=工厂());这段代码的作用是检测当前运行环境支持哪种模块化规范,然后对Vue进行模块化,其中exports是CommonjsSpecification,define是AMD的规范。正如您在源代码中看到的,factory()最终返回一个Vue对象。当检测为Commonjs规范时,导出Vue对象的方式为:module.exports=factory();当检测为AMD规范时,写成:define(factory)。为了更直观,重写这段代码:if(typeofexports==='object'&&typeofmodule!=='undefined'){//Commonjs规范module.exports=factory();}elseif(typeofdefine==='function'&&define.amd){//AMD规范define(factory);}else{//在其他情况下,将Vue挂载到全局对象//在浏览器中,将Vue属性添加到Window对象,属性值是factory()返回的Vue对象global=global||自我,global.Vue=factory();}