1. 虚拟DOM是什么?

虚拟 DOM 就是 虚拟节点,React 用 JS 对象模拟 DOM 节点, 然后再渲染成真实的 DOM 节点

2. 怎么实现的?

  • 第一步是模拟

用 jsx 语法写出来的 div 就是一个虚拟节点

  1. <div id="x">
  2. <span className="red">hi</span>
  3. </div>

这代码会得到一个对象

  1. {
  2. tag: 'div',
  3. props: {
  4. id: 'x'
  5. },
  6. children: [
  7. {
  8. tag: 'span',
  9. props: {
  10. className: 'red'
  11. },
  12. children: [
  13. 'hi'
  14. ]
  15. }
  16. ]
  17. }

能做到这一点是因为 JSX 语法会被转译为 createElement 函数调用 (也叫 h 函数),如下:

  1. React.createElement('div', {id: 'x'},
  2. React.createElement('span', { class: 'red' }, 'hi')
  3. )
  • 第二步是将虚拟节点渲染为真实节点 ```jsx function render(vdom) { // 如果是字符串或者数字,创建一个文本节点 if (typeof vdom === ‘string’ || typeof vdom === ‘number’) { return document.createTextNode(vdom) } const { tag, props, children } = vdom // 创建真实DOM const element = document.createElement(tag) // 设置属性 setProps(element, props) // 遍历子节点,并获取创建真实DOM,插入到当前节点 children .map(render) .forEach(element.appendChild.bind(element))

    // 虚拟 DOM 中缓存真实 DOM 节点 vdom.dom = element

    // 返回 DOM 节点 return element }

function setProps // 略 function setProp // 略 ``` 如果节点发生变化,并不会直接把新虚拟节点渲染到真实节点,而是先经过 diff 算法得到一个 patch 再更新到真实节点上

3. 解决了什么问题?

  • DOM 操作性能问题。通过虚拟 DOM 和 diff 算法减少不必要的 DOM 操作,保证性能不太差
  • DOM 操作不方便问题。以前需要记各种 DOM API 来操作 DOM,现在只需要使用 setState

    4. 优点

  • 为 React 带来了跨平台能力,因为虚拟节点除了渲染为真实节点,还可以渲染成其他东西。

  • 让 DOM 操作的整体性能更好,通过 diff 减少不必要的 DOM 操作

    5. 缺点

  • 性能要求极高的地方还得用真实 DOM 操作

  • React 为虚拟 DOM 创造了合成事件,跟原生 DOM 事件不太一样,工作中需要额外注意
    • 所有 React 事件都绑定到根元素,自动实现事件委托
    • 如果混用合成事件和原生 DOM 事件,有可能会出 bug