vue核心笔记

73 阅读2分钟

我正在参加「掘金·启航计划」

我们用最简单的方式一步一步实现vue核心吧

为什么需要 diff?

本质上就是为了性能,性能,性能,但是这里还是需要知道为啥 dom 操作容易慢,注意,不是说 dom 操作慢... *

  • 数据模型 -> virtual dom -> 视图(DOM)
  • f(state) -> View

why O(n)?

严格意义不是真的O(n),复杂度其实是O(nm)

how O(n)?

同层级比较 react 是怎么设计将复杂度砍下来呢?其实就是在算法复杂度、虚拟 dom 渲染机制、性能中找了一个平衡,react 采用了启发式的算法,做了如下最优假设:

  • a. 如果节点类型相同,那么以该节点为根节点的 tree 结构,大概率是相同的,所以如果类型不同,可以直接「删除」原节点,「插入」新节点
  • b. 跨层级移动子 tree 结构的情况比较少见,或者可以培养用户使用习惯来规避这种情况,遇到这种情况同样是采用先「删除」再「插入」的方式,这样就避免了跨层级移动
  • c. 同一层级的子元素,可以通过 key 来缓存实例,然后根据算法采取「插入」「删除」「移动」的操作,尽量复用,减少性能开销
  • d. 完全相同的节点,其虚拟 dom 也是完全一致的
  • 基于这些假设,可以将 diff 抽象成只需要做同层比较的算法,这样复杂度就直线降低了

用index做key

vue: [0,1,2],[0,1] 误删 react: 会重新渲染 都是新建

虚拟dom过程

虚拟 DOM

  1. 什么是虚拟 DOM
{
 type: 'div',
 props: {
 children: []
 },
 el: xxxx
}
  1. 怎么创建虚拟 DOM
 -> h 、createElement...
 function h(type, props) { return { type, props } }
  1. 使用呢
 JSX:
 <div>
  <ul className='padding-20'>
    <li key='li-01'>this is li 01</li>
  </ul>
 </div>

经过一些工具转一下:

createElement('div', {
 children: [
   createElement('ul', { className: 'padding-20' },
   createElement('li', { key: 'li-01'}, 'this is li 01'))
 ]
})
  1. 虚拟DOM的数据结构有了,那就是渲染了 (mount/render)
f(vnode) -> view

f(vode) {
document.createElement();
....

parent.insert()
. insertBefore
}

export const render = (vnode, parent) => {  }

<div id='app'></div>
  1. diff 相关了(patch)
f(oldVnodeTree, newVnodeTree, parent) -> 调度? -> view