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的运行结果。