「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > 仮想 DOM でコンポーネントがレンダリングされる方法と再レンダリングを最適化する方法

仮想 DOM でコンポーネントがレンダリングされる方法と再レンダリングを最適化する方法

2024 年 11 月 7 日に公開
ブラウズ:341

How Components are Rendered in a Virtual DOM and How to Optimize Re-Rendering

最新の Web アプリケーションを構築する場合、アプリの高速性と応答性を維持するには、UI (ユーザー インターフェイス) を効率的に更新することが不可欠です。多くのフレームワーク (React など) で使用される一般的な戦略は、仮想 DOMコンポーネント を使用することです。この記事では、仮想 DOM を使用してコンポーネントがどのようにレンダリングされるか、またウェブ アプリが遅くならないように 再レンダリングを最適化する方法について説明します。

1. 仮想 DOM とは何ですか?

DOM (ドキュメント オブジェクト モデル) は、Web ページ上のすべての要素を表すツリー状の構造です。ボタンをクリックしたりテキストを入力したりして Web ページを操作するたびに、ブラウザは DOM を更新する必要があり、時間がかかる場合があります。

仮想 DOM は実際の DOM のコピーに似ていますが、メモリ内にのみ存在します。何かが変更されるたびに実際の DOM を直接更新するのではなく、最初に仮想 DOM を更新します。変更が加えられると、仮想 DOM はそれ自体を古いバージョンと比較し、相違点を見つけ (これを 差分 と呼びます) し、変更が必要な実際の DOM の部分のみを更新します。

2. コンポーネントとは何ですか?

最新の Web アプリでは、コンポーネントが UI の構成要素です。これらは、Web ページの再利用可能な小さな部分であると考えてください。例えば:

  • ボタンはコンポーネントにすることができます。
  • ヘッダーはコンポーネントにすることができます。
  • アイテムのリストはコンポーネントにすることができます。

各コンポーネントは、UI のどの部分がどのように見えるべきかを記述します。 コンポーネント関数は、その UI を表す 仮想 DOM ツリーを返します。

3. 例: ボタンコンポーネントの作成

疑似コードを使用して、単純な Button コンポーネントを作成してみましょう。このコンポーネントは、テキストを含むボタンと、ボタンがクリックされたときに実行される関数を返します。

// Component to display a button
function Button(props) {
    // The Button component returns a Virtual DOM node for a 

この例では:

  • Button コンポーネントは、ボタンのテキストやボタンがクリックされたときのイベント ハンドラーなど、props (プロパティ) を受け取ります。
  • 指定されたテキストと onClick イベント ハンドラーを含む

4. 複数のコンポーネントのレンダリング

ヘッダーボタンを持つアプリを構築したいとします。これらの各部分はコンポーネントとして表すことができます。アプリの構造は次のようになります:

// App component with a header and button
function App() {
    return new VirtualNode("div", {}, [
        new Header(), // The Header component
        new Button({ text: "Click Me", onClick: handleClick }) // The Button component
    ])
}

// Header component
function Header() {
    return new VirtualNode("h1", {}, ["Welcome to the App!"])
}

// Function to handle button clicks
function handleClick() {
    console.log("Button clicked!")
}
  • App コンポーネントは、ヘッダーとボタンの 2 つのコンポーネントを含む 仮想 DOM ツリーを返します。
  • Header コンポーネントは、

    要素を表す仮想 DOM ノードを返します。

  • Button コンポーネントは前に説明したように機能します。

5. 初期レンダリングの仕組み

アプリを初めて実行すると、次のようになります:

  1. コンポーネントを呼び出します: App()、Header()、および Button() が実行されます。
  2. 仮想 DOM を作成します: 結果は、UI を表す仮想 DOM ノードのツリーです。
  3. 実際の DOM を更新します: 仮想 DOM は、実際の DOM 内に実際の HTML 要素を構築するために使用されます。
// Initial render of the app
function renderApp() {
    let virtualDOM = App()          // Render the app's Virtual DOM
    let realDOM = createRealDOM(virtualDOM)  // Convert the Virtual DOM into real DOM elements
    attachToPage(realDOM)           // Attach the real DOM elements to the webpage
}

6. 再レンダリングと最適化が必要な理由

ボタンのテキストなど、アプリ内の何かが変更されたとします。通常、アプリ全体が再レンダリングされますが、アプリが大きい場合、これは遅くなる可能性があります。代わりに、変更された部分のみを更新することで再レンダリングを最適化できます。

再レンダリングが発生すると次のようになります:

  1. 相違: 古い仮想 DOM と新しい仮想 DOM を比較し、何が変更されたかを調べます。
  2. パッチング: 更新する必要がある実際の DOM の部分のみが変更されます (このプロセスは パッチング と呼ばれます)。

例: ボタンのテキストの変更

ボタンのテキストが「Click Me」から「Clicked!」に変わったとします。ボタンを再レンダリングする方法は次のとおりです:

// New Button component with updated text
function Button(props) {
    return new VirtualNode("button", { onClick: props.onClick }, [props.text])
}

// Re-rendering with the new text
let oldButton = Button({ text: "Click Me", onClick: handleClick })
let newButton = Button({ text: "Clicked!", onClick: handleClick })

// Diff the old and new Button
let diffResult = diff(oldButton, newButton)

// Patch the real DOM with the changes
patch(realButtonDOM, diffResult)

7. 再レンダリングの最適化: コンポーネントを更新する必要があります

再レンダリングを最適化する重要な方法の 1 つは、コンポーネントを実際に更新する必要があるかどうかを確認することです。コンポーネントの props または state に何も変更がない場合は、そのコンポーネントの再レンダリングをスキップできます。ここで、 shouldComponentUpdate ロジックが登場します。

// Function to check if a component should update
function shouldComponentUpdate(oldProps, newProps) {
    return oldProps !== newProps // Only update if the props have changed
}

次に、再レンダリングする前に、コンポーネントを更新する必要があるかどうかを確認します:

// Example: Optimized re-rendering of Button component
function renderButtonIfNeeded(oldButton, newButton) {
    if (shouldComponentUpdate(oldButton.props, newButton.props)) {
        let realButton = createRealDOM(newButton)
        patch(realButton)
    }
}

8. リストの最適化のためのキーの使用

項目のリスト (ボタンのリストなど) をレンダリングする場合、keys を使用して各項目を一意に識別することで最適化できます。これにより、差分アルゴリズムがリスト内の古い項目と新しい項目を照合し、必要な変更のみを適用するのに役立ちます。

// List of buttons with unique keys
function ButtonList(items) {
    return new VirtualNode("div", {}, items.map(item => 
        new Button({ key: item.id, text: item.text, onClick: handleClick })
    ))
}

キーを使用すると、リスト内の項目の 1 つが変更された場合 (ボタンの追加または削除など)、アルゴリズムは変更されたボタンをすぐに識別し、そのボタンのみを更新できます。

9. 状態変化の最適化

コンポーネントは独自の 状態を持つこともできます。コンポーネントの状態が変化したとき、アプリ全体ではなく、その特定のコンポーネントのみを再レンダリングする必要があります。以下は状態を含むボタンの例です:

// Button component with state
function ButtonWithState() {
    let [clicked, setClicked] = useState(false) // Create state for button

    function handleClick() {
        setClicked(true) // Update state when clicked
    }

    return new VirtualNode("button", { onClick: handleClick }, [clicked ? "Clicked!" : "Click Me"])
}

この場合:

  • クリックするとボタンのテキストが変わります。
  • ButtonWithState コンポーネントのみが再レンダリングされ、実際の DOM はボタン テキストのみを更新します。

10. 親コンポーネントの再レンダリングを避ける

もう 1 つの最適化は、子コンポーネントのみが変更された場合に親コンポーネントの再レンダリングを回避することです。たとえば、ボタンが変更されてもヘッダーが同じままの場合、ヘッダーの再レンダリングをスキップできます。

// Optimized App component
function App() {
    if (!shouldComponentUpdate(oldHeaderProps, newHeaderProps)) {
        return oldHeader // Reuse the old Header if it hasn't changed
    }

    return new VirtualNode("div", {}, [
        new Header(), // Re-render the Header only if necessary
        new ButtonWithState() // Button re-renders based on state
    ])
}

11. 結論: 仮想 DOM を使用した効率的な UI 更新

要約すると、仮想 DOM を使用してコンポーネントをレンダリングおよび最適化するプロセスを次のステップに分けることができます:

  1. 初期レンダリング: アプリが初めてレンダリングされるときに、仮想 DOM ツリーを構築し、それを実際の DOM に変換します。
  2. 再レンダリング: 何かが変更されると (ボタンのテキストや状態など)、仮想 DOM が更新され、必要な変更のみが実際の DOM に適用されます。
  3. 再レンダリングの最適化: shouldComponentUpdate、リストのキー、状態ベースの更新などの戦略を使用することで、不必要な再レンダリングを回避し、アプリの高速性と応答性を維持できます。

いつ、何を再レンダリングするかを慎重に考えることで、Web アプリケーションが複雑になっても効率を維持できるようになります。 Virtual DOM は、シンプルさとパフォーマンスのバランスを実現するのに役立つ強力なツールです!

リリースステートメント この記事は次の場所に転載されています: https://dev.to/biswasprasana001/how-components-are-rendered-in-a-virtual-dom-and-how-to-optimize-re-rendering-5f61?1侵害がある場合は、削除するには[email protected]までご連絡ください。
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3