一:nextTick在哪里使用?原理是?
核心答案:
nextTick的回调是在下次DOM更新循环结束之后执行的延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。nextTick主要使用了宏任务和微任务。原理就是异步方法(promise, mutationObserver, setImmediate, setTimeout)经常与事件循环一起来问。
补充回答:
vue多次更新数据,最终会进行批处理更新。内部调用的就是nextTick实现了延迟更新,用户自定义的nextTick中的回调会被延迟到更新完成后调用,从而可以获取更新后的DOM。
源码地址:src/core/util/next-tick.js 42
二:Vue 为什么需要虚拟DOM? 虚拟DOM的优劣如何?
核心答案:
Virtual DOM 就是用js对象来描述真实DOM,是对真实DOM的抽象,由于直接操作DOM性能低但是js层的操作效率高,可以将DOM操作转化成对象操作,最终通过diff算法比对差异进行更新DOM (减少了对真实DOM的操作)。虚拟DOM不依赖真实平台环境从而也可以实现跨平台。
补充回答:
虚拟DOM的实现就是普通对象包含tag、data、children等属性对真实节点的描述。(本质上就是在JS和DOM之间的一个缓存)
Vue2的 Virtual DOM 借鉴了开源库snabbdom的实现。
VirtualDOM映射到真实DOM要经历VNode的create、diff、patch等阶段。
源码地址:src/core/vdom/vnode: 3
三:Vue中key的作用和工作原理,说说你对它的理解?
核心答案:
例如:v-for="(item, itemIndex) in tabs" :key="itemIndex"
key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能。
补充回答:
1、若不设置key还可能在列表更新时引发一些隐蔽的bug
2、vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
源码地址:src\core\vdom\patch.js - updateChildren()
四:Vue 中的diff原理
核心答案:
vue的diff算法是平级比较,不考虑跨级比较的情况。内部采用深度递归的方式 + 双指针的方式进行比较。
补充回答:
1) 先比较是否是相同节点
2) 相同节点比较属性,并复用老节点
3) 比较儿子节点,考虑老节点和新节点儿子的情况
4) 优化比较:头头、尾尾、头尾、尾头
5) 比对查找进行复用
Vue2 与 Vue3.x 的diff算法:
Vue2的核心Diff算法采用了双端比较的算法,同时从新旧children的两端开始进行比较,借助key值找到可复用的节点,再进行相关操作。
Vue3.x借鉴了ivi算法和 inferno算法,该算法中还运用了动态规划的思想求解最长递归子序列。(实际的实现可以结合Vue3.x源码看。)
源码地址:src/core/vdom/patch.js 501
五:v-if 与 v-for的优先级
核心答案:
1、v-for优先于v-if被解析
2、如果同时出现,每次渲染都会先执行循环再判断条件,无论如何循环都不可避免,浪费了性能
3、要避免出现这种情况,则在外层嵌套template,在这一层进行v-if判断,然后在内部进行v-for循环
4、如果条件出现在循环内部,可通过计算属性提前过滤掉那些不需要显示的项
源码地址:compiler/codegen/index.js
六:v-if与v-show的区别
核心答案:
v-if 是真正的条件渲染,直到条件第一次变为真时,才会开始渲染。
v-show 不管初始条件是什么会渲染,并且只是简单地基于 CSS 的 “display” 属性进行切换。
注意:v-if 适用于不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
七:computed 和 watch 的区别和运用的场景?
核心答案:
computed: 计算属性。依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 监听数据的变化。更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
运用场景:
1)当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
2)当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
八:如何理解自定义指令?
核心答案:
指令的实现原理,可以从编译原理 =>代码生成=> 指令钩子实现进行概述
1、在生成 ast 语法树时,遇到指令会给当前元素添加directives属性
2、通过 genDirectives 生成指令代码
3、在patch前将指令的钩子提取到 cbs中,在patch过程中调用对应的钩子。
4、当执行指令对应钩子函数时,调用对应指令定义的方法
九:V-model的原理是什么?
核心答案:
v-model本质就是一个语法糖,可以看成是value + input方法的语法糖。可以通过model属性的prop和event属性来进行自定义。原生的v-model,会根据标签的不同生成不同的事件和属性。
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
1)text 和 textarea 元素使用 value 属性和 input 事件;
2)checkbox 和 radio 使用 checked 属性和 change 事件;
3)select 字段将 value 作为 prop 并将 change 作为事件。
来自VUE中文社区公众号 https://mp.weixin.qq.com/s/60HI-CM1GhqDG5zeTFSOrw