1.nextTick原理

Vue是异步执行Dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环(event loop)当中观察到数据变化的Watcher推送到这个队列。如果这个Watcher被触发多次,智慧被推送到队列一次。这种缓冲行为可以有效去掉重复数据造成的不必要的计算和DOM操作。而在下一个事件循环时,Vue会清空队列,并进行必要的Dom更新。当你设置vm(this).someData='new value',DOM并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的Dom更新。如果此时你想要根据更新的DOM状态去做某些事情,就会出现问题。为了在数据变化之后等待Vue完成更新Dom,可以在数据变化之后立即使用Vue.nextTick(callback)。这样回调函数在DOM更新完成后就会调用。

2.Data为什么是一个函数

在Vue组件中,data选项必须是一个函数,而不能直接是一个对象。这是因为Vue组件可以同时存在多个实例,如果直接使用对象形式的data选项,那么所有的实例将会共享同一个data对象,这样就会造成数据相互干扰的问题。因此,将data选项设置为函数可以让每个实例都拥有自己独立的data对象。

3.为什么循环的时候需要加key?

作用:key的作用主要是为了高效的更新虚拟DOM,提高渲染性能。key属性可以避免数据混乱的情况出现。

原理:

①Vue实现了一套虚拟Dom,使我们可以不直接操作Dom元素之操作数据,就可以重新渲染页面,而隐藏在背后的原理是高效的Diff算法。

②当页面数据发生变化时,Diff只会比较同一层级的节点。

③如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点后面的子节点;如果节点类型相同,则会重新设置该节点的属性,从而实现节点更新。

④使用key给每一个节点做一个唯一标识,Diff算法就可以正确识别此节点,“”“就地更新查找到正确的位置插入新的节点。

4.有哪些常见的Loader?你用过哪些Loader?

Raw-loader:加载文件原始内容(utf-8)

file-Loader:把文件输出为一个文件夹中,在代码中通过相对URL去引用输出的文件(处理图片和字体)

url-loader:与file-loader类似,区别是用户可以设置一个阈值,大于阈值会交给file-loader处理,小于阈值时返回文件base64形式编码(处理图片和字体)

Source-map-Loader:加载额外的Source map文件,以方便断点调试

svg-inline-loader:将压缩后的svg内容注入代码中

image-loader:加载并且压缩图片文件

json-loader:加载json文件

handlebars-loader:将handlebars模板编译成函数并返回。

Babel-loader:把ES6转换成ES5

ts-loader:将Typescript转换成JavaScript

awesome-Typescript-loader:将Typescript转换成JavaScript,性能优于ts-loader。

Sass-loader:将scss/sass代码转换成css

css-loader:加载css,支持模块化、压缩、文件导入等特性。

style-loader:把css代码注入到JavaScript中,通过Dom操作去加载css。

postcss-loader:扩展css语法,使用下一代css,可以配合autoprefixer插件自动补齐css3前缀。

eslint-loader:通过eslint检查JavaScript代码

tslint-loader:通过tslint检查Typescript代码。

Mocha-loader:加载Mocha测试用例的代码

coverjs-loader:计算测试的覆盖率

Vue-loader:加载Vue.js单文件组件。

i18n-loader:国际化

cache-loader:可以在一些性能开销较大的Loader之前添加,目的是将结果缓存到磁盘里

2.有哪些常见的plugin?你用过哪些plugin?

define-plugin:定义环境变量(Webpack4之后指定model会自动配置)

ignore-plugin:忽略部分文件。

html-Webpack-plugin:简化HTML文件创建(依赖于html-loader)

Web-Webpack-plugin:可方便地为单页应用输出HTML,比html-Webpack-plugin好用

uglifyjs-Webpack-plugin:不支持ES6压缩(Webpack4以前)

terser-Webpack-plugin:支持ES6压缩(Webpack4)

Webpack-parallel-uglify-plugin:多进程执行代码压缩。提升构建速度。

mini-css-extract-plugin:分离样式文件,css提取为独立文件,支持按需加载(替代extract-text-webpack-plugin)

serviceworker-webpack-plugin:为网页增加离线缓存功能

clean-webpack-plugin:目录清理

ModuleConcatenationPlugin:开启Scope hoisting

speed-measure-webpack-plugin:可以看到每个loader和plugin执行耗时(整个打包耗时、每个Plugin和Loader耗时)

Webpack-bundle-analyzer:可视化Webpack输出文件的体积(业务组件、依赖第三方模块)

3.说一说Loader和Plugin的区别?

Loader本质是一个函数,在该函数中对接到的内容进行转换,返回转换后的结果。因为Webpack只认识JavaScript,所以Loader就成了翻译官,对其他类型的资源进行转译的预处理工作。

Plugin就是插件,基于事件流框架Tapable,插件可以扩展Webpack的功能,在Webpack运行的声明周期中会广播出许多事件,Plugin可以监听这些事件,在合适的时机通过Webpack提供的API改变输出结果。

Loader在module.rules中配置,作为模板的解析规则,类型为数组。每一项都是一个Object,内部包含了test(类型文件)、loader、options(参数)等属性。

Plugin在plugins中单独配置,类型为数组,每一项是一个Plugin的实例,参数都通过构造函数传入。

4.Webpack打包流程

Webpack的打包流程是一个串行的过程,从启动到结束会依次执行以下流程:

①初始化参数:从配置文件和shell语句中读取与合并参数,得出最终的参数

②开始编译:用上一步得到的参数初始化Complier对象,加载所有配置的插件,执行对象的run方法开始执行编译。

③确定入口:根据配置中的entry找出所有的入口文件。

④编译模块:从入口文件触发,调用所有配置的Loader对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直至所有入口依赖文件都经过了本步骤的处理

⑤完成模块编译:在经过第4步使用Loader翻译完所有模板后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系。

⑥输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk,再把每个Chunk转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。

⑦输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

在以上过程中,Webpack会特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用Webpack提供的API改变Webpack的运行结果。