前端面试押题
  • HTML
    • 有哪些新标签?
    • SVG 的区别是什么?
    • 如何理解 HTML 中的语义化标签
  • CSS
    • 如何清除浮动?
    • CSS 选择器优先级如何确定?
    • BFC 是什么
    • 两种盒模型(box-sizing)的区别?
    • 如何实现垂直居中?
  • JavaScript 押题基础篇
    • new 做了什么?
    • JS 如何实现类?
    • JS 的闭包是什么?怎么用?
    • JS 如何实现继承?
    • JS 的立即执行函数是什么?
    • JS 的数据类型有哪些?
    • 原型链是什么?
    • 这段代码中的 this 是多少?
  • JavaScript 押题手写篇
    • 手写数组去重
    • 手写简化版 Promise
    • 手写 AJAX
    • 手写深拷贝
    • 手写节流 throttle、防抖 debounce
    • 手写发布订阅
    • 手写 Promise.all
  • DOM 押题
    • 请简述 DOM 事件模型
    • 手写可拖曳 div
    • 手写事件委托
  • HTTP 押题
    • 说说同源策略和跨域
    • POST 的区别有哪些?
    • TCP 三次握手和四次挥手是什么?
    • Session、Cookie、LocalStorage、SessionStorage 的区别
    • HTTP 缓存有哪些方案?
    • HTTPS 的区别有哪些?
    • HTTP/2 的区别有哪些?
  • React 押题
    • 什么是高阶组件 HOC?
    • React Hooks 如何模拟组件生命周期?
    • 你如何理解 Redux?
    • React 有哪些生命周期钩子函数?数据请求放在哪个钩子里?
    • React 如何实现组件间通信
    • 虚拟 DOM 的原理是什么?
    • Vue DOM diff 的区别?
    • DOM diff 算法是怎样的?
  • Node.js 押题
    • 浏览器里的微任务和任务是什么?
    • EventLoop 是什么?
    • koa.js 的区别是什么?
  • TypeScript 押题
    • JS 的区别是什么?有什么优势?
    • any、unknown、never 的区别是什么?
    • TS 工具类型 Partial、Required、Readonly、Exclude、Extract、Omit、ReturnType 的作用和实现?
    • interface 的区别是什么?
Powered by GitBook
On this page
  1. React 押题

虚拟 DOM 的原理是什么?

  1. 是什么

    虚拟 DOM 就是虚拟节点(这句汉化很重要)。React 用 JS 对象来模拟 DOM 节点,然后将其渲染成真实的 DOM 节点。

  2. 怎么做

    第一步是模拟

    用 JSX 语法写出来的 div 其实就是一个虚拟节点:

    <div id="x">
      <span class="red">hi</span>
    </div>

    这代码会得到这样一个对象:

    {
      tag: 'div',
      props: {
        id: 'x'
      },
      children: [
        {
          tag: 'span',
          props: {
            className: 'red'
          },
          children: [
            'hi'
          ]
        }
      ]
    }

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

    React.createElement("div", { id: "x"}, 
      React.createElement("span", { class: "red" }, "hi")
    )

    第二步是将虚拟节点渲染为真实节点

    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 // 略
    
    // 作者:Shenfq
    // 链接:https://juejin.cn/post/6844903870229905422

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

  3. 解决了什么问题

    1. DOM 操作性能问题。通过虚拟 DOM 和 diff 算法减少不必要的 DOM 操作,保证性能不太差

    2. DOM 操作不方便问题。以前各种 DOM API 要记,现在只有 setState

  4. 优点

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

    2. 让 DOM 操作的整体性能更好,能(通过 diff)减少不必要的 DOM 操作。

  5. 缺点

    1. 性能要求极高的地方,还是得用真实 DOM 操作(目前没遇到这种需求)

    2. React 为虚拟 DOM 创造了合成事件,跟原生 DOM 事件不太一样,工作中要额外注意

      1. 所有 React 事件都绑定到根元素,自动实现事件委托

      2. 如果混用合成事件和原生 DOM 事件,有可能会出 bug

  6. 如何解决缺点

    不用 React,用 Vue 3(笑)

PreviousReact 如何实现组件间通信NextVue DOM diff 的区别?

Last updated 3 years ago