React原理:虛擬DOM(學(xué)習(xí)筆記)

虛擬 DOM介紹


虛擬 DOM(Virtual DOM)是 React 中的核心概念之一。為了理解它,首先需要知道直接操作真實(shí)的 DOM 是代價(jià)高昂的,因?yàn)檫@可能引起瀏覽器的重排和重繪,導(dǎo)致性能瓶頸。虛擬 DOM 旨在最小化與真實(shí) DOM 的交互次數(shù),從而提高性能。 以下是關(guān)于 React 中的虛擬 DOM 的詳細(xì)解釋?zhuān)?/p>

  1. 定義:虛擬 DOM 是對(duì)真實(shí) DOM 的輕量級(jí)表示。它是一個(gè) JavaScript 對(duì)象,映射了真實(shí) DOM 的結(jié)構(gòu)和屬性。
  2. 工作機(jī)制
  • 當(dāng) UI 的某個(gè)部分發(fā)生變化時(shí)(例如,因?yàn)橛脩?hù)輸入或新數(shù)據(jù)),React 會(huì)創(chuàng)建一個(gè)新的虛擬 DOM 樹(shù)。
  • 接著,React 會(huì)將新的虛擬 DOM 樹(shù)與上一個(gè)版本的虛擬 DOM 樹(shù)進(jìn)行比較,這一步被稱(chēng)為“差異化”(diffing)。
  • 通過(guò)這一比較過(guò)程,React 能夠確定真實(shí) DOM 需要進(jìn)行哪些最小的修改以反映新的 UI 狀態(tài)。
  • 最后,React 將這些變化批量應(yīng)用到真實(shí)的 DOM,這一步被稱(chēng)為“重新渲染”(reconciliation)。
  1. 優(yōu)勢(shì)
  • 性能提高:通過(guò)批量更新真實(shí) DOM,并只修改必要的部分,React 可以減少昂貴的 DOM 操作和不必要的重排/重繪。
  • 編程簡(jiǎn)化:開(kāi)發(fā)者不必關(guān)心如何高效地更新 DOM。他們只需聲明 UI 在各種狀態(tài)下的外觀,而 React 負(fù)責(zé)如何實(shí)現(xiàn)這一過(guò)程。
  • 跨平臺(tái):由于虛擬 DOM 只是 JavaScript 對(duì)象,因此 React 可以在不同環(huán)境中重復(fù)使用相同的邏輯,例如在 React Native 中。
  1. 局限性
  • 雖然虛擬 DOM 提高了性能,但它并不是解決所有問(wèn)題的銀彈。在某些情況下,對(duì)真實(shí) DOM 的直接操作可能更快。
  • 差異化和重新渲染仍然需要計(jì)算資源。對(duì)于大型應(yīng)用或頻繁的更新,開(kāi)發(fā)者可能需要使用一些性能優(yōu)化技巧。 總之,虛擬 DOM 是 React 如何快速和高效地更新 UI 的核心機(jī)制。通過(guò)將復(fù)雜的 DOM 更新邏輯抽象為簡(jiǎn)單的 JavaScript 運(yùn)算,React 提供了一個(gè)強(qiáng)大且高性能的方法來(lái)構(gòu)建動(dòng)態(tài) web 應(yīng)用。

模擬創(chuàng)建虛擬 DOM——createElement


封裝createElement

src\react.js

function createElement(type, config, children) {
  let props = { ...config };
  if (arguments.length > 3) {
    props.children = Array.prototype.slice.call(arguments, 2);
  } else {
    props.children = children;
  }
  return {
    type,
    props,
  };
}
const React = {
  createElement,
};
export default React;
引入createElement創(chuàng)建虛擬DOM

src\index.js

import React from "./react";
const element = React.createElement(
  "div",
  {
    style: {
      color: "red",
    },
    className: "wrapper",
  },
  "hello",
  React.createElement(
    "span",
    {
      style: {
        color: "blue",
      },
    },
    "world"
  )
);
console.log(JSON.stringify(element));

輸出結(jié)果:

{
  "type": "div",
  "props": {
    "style": { "color": "red" },
    "className": "wrapper",
    "children": [
      "hello",
      {
        "type": "span",
        "props": { "style": { "color": "blue" }, "children": "world" }
      }
    ]
  }
}

模擬渲染虛擬 DOM——createRoot


封裝createRoot

src\react-dom\client.js

function createRoot(container) {
  return {
    render(reactElement) {
      const domElement = renderElement(reactElement);
      container.appendChild(domElement);
    },
  };
}
function renderElement(element) {
  if (typeof element === "string") {
    return document.createTextNode(element);
  }
  const { type, props } = element;
  const domElement = document.createElement(type);
  Object.keys(props).forEach((name) => {
    if (name === "children") {
      return;
    }
    if (name === "style") {
      Object.assign(domElement.style, props.style);
    } else if (name.startsWith("on")) {
      const eventName = name.toLowerCase().substring(2);
      domElement.addEventListener(eventName, props[name]);
    } else {
      domElement[name] = props[name];
    }
  });
  if (typeof props.children !== "undefined") {
    const children = Array.isArray(props.children)
      ? props.children
      : [props.children];
    children.forEach((child) => domElement.appendChild(renderElement(child)));
  }
  return domElement;
}
const ReactDOMClient = {
  createRoot,
};
export default ReactDOMClient;
引入createRoot渲染虛擬 DOM

src\index.js

import React from "./react";
import ReactDOM from "./react-dom/client";
const element = React.createElement(
  "div",
  {
    style: {
      color: "red",
    },
    className: "wrapper",
  },
  "hello",
  React.createElement(
    "span",
    {
      style: {
        color: "blue",
      },
    },
    "world"
  )
);
ReactDOM.createRoot(document.getElementById("root")).render(element);

渲染結(jié)果:

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容