vue 底层面试题

vue的底层原理面试题

1. diff的比较方式? ok

在采取diff算法比较新旧节点的时候,比较只会在同层级进行, 不会跨层级比较。
如果两个节点都是一样的,那么就深入检查他们的子节点。
果两个节点不一样那就说明 Vnode 完全被改变了(ul和div节点不一样),
就可以直接使用新节点替换老节点。【他们的子代不会进行比较了】 

<div>
 <p>123</p>
</div>
 
<div>
 <span>456</span>
</div>
上面的代码会分别比较同一层的两个div以及第二层的p和span,但是不会拿div和span作比较。

2. virtual DOM和真实DOM的区别? ok

virtual DOM是将[真实的DOM的数据]抽取出来,以对象的形式[模拟]树形结构。比如dom是这样的:
或者说 
<div>
 <p>123</p>
</div>
对应的virtual DOM(伪代码):
var Vnode = {
 tag: 'div',
 children: [
  { tag: 'p', text: '123' }
 ]
};
(温馨提示: VNode 和 oldVNode 都是对象,一定要记住)

3. patch 函数的分析 ok

function patch (oldVnode, vnode) {
 if (sameVnode(oldVnode, vnode)) {
  patchVnode(oldVnode, vnode)
 } else {
  const oEl = oldVnode.el // 当前oldVnode对应的真实元素节点
  let parentEle = api.parentNode(oEl) // 父元素
  createEle(vnode) // 根据Vnode生成新元素
  if (parentEle !== null) {
   api.insertBefore(parentEle, vnode.el, api.nextSibling(oEl)) // 将新元素添加进父元素
   api.removeChild(parentEle, oldVnode.el) // 移除以前的旧元素节点
   oldVnode = null
  }
 }
 // some code 
 return vnode
}


patch函数接收两个参数 oldVnode 和 Vnode 分别代表旧节点和新节点
如果两个节点都是一样的,那么就深入检查他们的子节点。
如果两个节点不一样那就说明 Vnode 完全被改变了,就可以直接替换 oldVnode 。

4. 如何节点是真实的节点path函数如何处理?

//是虚拟节点还是dom节点,如果是dom节点包装成虚拟节点
if (!isVnode(oldVnode)) {
    oldVnode = emptyNodeAt(oldVnode);
}
处理方式:
1.是虚拟节点还是dom节点,如果是dom节点包装成虚拟节点

5. 如何知道是虚拟节点还是DOM节点呢 ?

export default function (oldVnode,newVnode) {
  // 通过sel属性或者tag属性是否为空或者undefined说明是DOM节点
  if (oldVnode.sel=='' || oldVnode.sel==undefined) {
    // 说明第一个参数是DOM节点,
   //  通过vnode 将DOM节点包装成虚拟dom节点 
  }
}
因为真实DOM节点sel属性肯定不是false
再更新节点的时候是:先插入然后再删除

6. 对diff算法的命中查找的解释

1、新前与旧前
命中结果:新前与旧前下标同时下移  ↓
2、新后与旧后
命中结果:新前与旧前下标同时上移  ↑
巧计:1-2相同,只变前面那一个字。

3、新后与旧前
命中结果:移动新前指向的这个节点到老节点的旧后之后 。
4、新前与旧后
命中结果:移动新前指向的这个节点到老节点的旧前前面。
3-4相反,
共同点:都是前开头

注意的点:
1、命中一种就不在往下判断了。如果都命中不了,就创建一个map映射,移动到旧节点最初的的位置
2、如果旧节点先循环完毕==》说明新节点有要插入的节点

7. diff 了解

diff 算法时发生在虚拟Dom之间的。
是新的虚拟dom和老的虚拟dom之间的比较。【注意一下】
然后算出最小量之间的跟新,最后渲染到真正的Dom上
https://www.jb51.net/article/140471.htm

=明天继续======

1. nextTick 的原理

nextTick的原理:将回调延迟到下次 DOM 更新循环之后执行。

2. nextTick是如何实现的

Vue 在更新 DOM 是异步的,当监听数据变化后,vue会开启一个队列。
并缓冲同一个事件在循环中发生【所有数据变化后】,
如果同一个 watcher 被多次触发,只会被推入到队列中一次。
这种缓冲的意义在于,去除重复的数据,可以避免不必要计算和DOM操作。
Vue内部对异步队列尝试使用 Promise.then、
然后时是 MutationObserver 和 setImmediate 
如果前两者都不支持使用  setTimeout(fn, 0) 代替。
对当前环境进行不断的降级处理

【mjuːˈteɪ ʃn]】 Mutation   突变;变异;基因突变
【ɪn mi di ət 】   

也就是说我们在设置数据的时候,( this.msg = 'some thing' )
Vue并没有马上去更新DOM数据,而是将这个操作放进一个队列中
如果我们重复执行的话,队列还会进行去重操作。
等待同一事件【循环中】的所有数据变化完成之后。
会将事件从队列拿出来。


这样做主要是为了提升性能,
如果循环100次就要更新100次DOM,是非常消耗性能的。
但是如果等【事件循环完成】之后更新DOM,只需要更新1次。

3. nextTick 的流程就是:

1.把回调函数放入callbacks等待执行
2.将执行函数放到微任务或者宏任务中
3.事件循环到了微任务或者宏任务,依次执行callbacks中的回调

=明天继续==============

1. 当数据发生变化时,vue是怎么更新节点的?

在跟新的时候,调用patch函数。
函数会判断是虚拟节点还是DOM节点。
如果是DOM节点,将它包装成虚拟节点。
如果是虚拟节点:
如果两个节点都是一样的,那么就深入检查他们的子节点。
如果两个节点不一样那就说明 Vnode 完全被改变了,就可以直接替换 oldVnode 

1. Vue中的双向数据绑定是如何实现的

Vue的双向数据绑定是通过【数据劫持】结合【发布者订阅者】模式来实现的
条件:
1、实现一个数据监听器Observer,能够对数象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
(我的理解:Observer->监听->变化->通知 )

2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数

3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

链接:https://www.jianshu.com/p/9bd100c785ee

作者:明月人倚楼
出处:https://www.cnblogs.com/IwishIcould/

想问问题,打赏了卑微的博主,求求你备注一下的扣扣或者微信;这样我好联系你;(っ•̀ω•́)っ✎⁾⁾!

如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,或者关注博主,在此感谢!

万水千山总是情,打赏5毛买辣条行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主(っ•̀ω•́)っ✎⁾⁾!

想问问题,打赏了卑微的博主,求求你备注一下的扣扣或者微信;这样我好联系你;(っ•̀ω•́)っ✎⁾⁾!

支付宝
微信
本文版权归作者所有,欢迎转载,未经作者同意须保留此段声明,在文章页面明显位置给出原文连接
如果文中有什么错误,欢迎指出。以免更多的人被误导。
原文地址:https://www.cnblogs.com/IwishIcould/p/15756343.html