动态

详情 返回 返回

讓 React 擁有更快的虛擬 DOM - 动态 详情

Million.js 是一個非常快速和輕量級的 ( <4kb) 虛擬 DOM。框架可以通過包裝 React 組件來提升性能(該框架目前版本只兼容 React 18 及以上版本)。

先説結論:Million.js 適應的場景極其有限,但在特定場景下也大放異彩。

如何使用

Million.js 集成 React 中使用非常簡單。先進行安裝和編譯器配置。

安裝與配置

npm install million

當前是 webpack 的配置文件。如果有使用其他的構建工具,可以自行參考 安裝 Million.js。

const million = require('million/compiler');

module.exports = {
  plugins: [
    million.webpack(),
  ],
}

使用 block 和 For 組件

import { block as quickBlock } from "million/react";

// million block 是一個 HOC
const LionQuickBlock = quickBlock(function Lion() {
  return <img src="https://million.dev/lion.svg" />;
});

// 直接使用
export default function App() {
  return (
    <div>
      <h1>mil + LION = million</h1>
      <LionQuickBlock />
    </div>
  );
}

當前是數組的情況下

import { block as quickBlock, For } from "million/react";

const RowBlock = quickBlock(function Row({ name, age, phone }) {
  return (
    <tr>
      <td>{name}</td>
      <td>{age}</td>
      <td>{phone}</td>
    </tr>
  );
});

// 使用 For 組件優化
export default function App() {
  return (
    <div>
      <For each={data}>
        {({ adjective, color, noun }) => (
          <RowBlock 
            adjective={adjective}
            color={color} 
            noun={noun} 
          />
        )}
      </For>
    </div>
  );
}

Block Virtual DOM

Million.js 引入了 Block Virtual DOM 來進行優化。

Block Virtual DOM 採用不同的方法進行比較,可以分為兩部分:

  • 靜態分析(分析虛擬 DOM 以將 DOM 動態部分蒐集起來,放入 Edit Map 或者 edits(列表) 中去)
  • 髒檢查(比較狀態(不是虛擬 DOM 樹)來確定發生了什麼變化。如果狀態發生變化,DOM 將直接通過 Edit Map 進行更新)

這種方式大部分情況下要比 React 的虛擬 DOM 要快,因為它比較數據而並非 DOM,將樹遍歷從 O(tree) 變為 Edit Map O(1)。同時我們也可以看出 Million.js 也會通過編譯器對原本的 React 組件進行修改。

適用場景

但所有的事情都不是絕對的,Block Virtual DOM 在某些情況下甚至要比虛擬 DOM 要慢。

靜態內容多,動態內容少

block virtual DOM 會跳過 virtual DOM 的靜態部分。

// ✅ Good
<div>
  <div>{dynamic}</div>
  Lots and lots of static content...
</div>

// ❌ Bad
<div>
  <div>{dynamic}</div>
  <div>{dynamic}</div>
  <div>{dynamic}</div>
  <div>{dynamic}</div>
  <div>{dynamic}</div>
</div>

穩定的 UI 樹

因為 Edit Map 只創建一次,不需要在每次渲染時都重新創建。所以穩定的 UI 樹是很重要的。

// ✅ Good
return <div>{dynamic}</div>

// ❌ Bad
return Math.random() > 0.5 ? <div>{dynamic}</div> : <p>sad</p>;

細粒度使用

初學者犯的最大錯誤之一是到處使用 Block virtual DOM。這是個壞主意,因為它不是靈丹妙藥。開發者應該識別塊虛擬 DOM 更快的某些模式,並僅在這些情況下使用它。

規則

以下是一些要遵循的一般準則

  • 嵌套數據:塊非常適合呈現嵌套數據。Million.js 將樹遍歷從O(tree)變為O(1),允許快速訪問和更改。
  • 使用 For 組件而不是 Array.map:For 組件會做針對性優化
  • 使用前需要先聲明:編譯器需要進行分析,沒有申明將無法進行分析

    // ✅ Good
    const Block = block(<div />)
    
    // ❌ Bad
    console.log(block(<div />))
    export default block(<div />)
  • 傳遞組件而不是 JSX

    // ✅ Good
    const GoodBlock = block(App)
    
    // ❌ Bad
    const BadBlock = block(<Component />)
  • 確定的返回值:返回必須是“確定性的”,這意味着在返回穩定樹的塊末尾只能有一個返回語句(組件庫,Spread attributes 都有可能造成不確定的返回值而導致性能下降)

其他

million 源碼中有非常多的緩存優化。同時在它最開始就拆分傳入的 dom 節點,將其分成多個可變量,放入數組,patch 和 mount 時僅遍歷數組數據對比(這也是需要確定的返回值原因),較為新穎。源代碼也較為簡單明瞭。大家可以自行閲讀源碼學習。

  • million react/block.ts
  • million template.ts
  • million block.ts .

million 的 Block Virtual DOM 的思路來源於 blockdom, blockdom 是一個較低級別的抽象層。這個框架同時提供了製作框架的教程 製作自己的框架。

鼓勵一下

如果你覺得這篇文章不錯,希望可以給與我一些鼓勵,在我的 github 博客下幫忙 star 一下。

博客地址

參考資料

Million.js

blockdom

user avatar toopoo 头像 linlinma 头像 littlelyon 头像 zzd41 头像 smalike 头像 nznznz 头像 hea1066 头像 code500g 头像 fanudekaixinguo 头像 sy_records 头像 morimanong 头像 wubomu 头像
点赞 36 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.