說明
支持我們

外部 DOM 突變

有時需要使用第三方函式庫,這些函式庫預期能夠自由突變 DOM、在其中保留狀態,或根本沒有組件邊界。有許多很棒的 UI 工具包或可重複使用的元素以這種方式運作。

在 Preact(以及 React 中類似),使用這些類型的函式庫需要您告訴虛擬 DOM 渲染/差異演算法,它不應該嘗試還原在給定組件(或它所代表的 DOM 元素)中執行的任何外部 DOM 突變。



技巧

這可以像在你的元件上定義一個 shouldComponentUpdate() 方法一樣簡單,並讓它回傳 false

class Block extends Component {
  shouldComponentUpdate() {
    return false;
  }
}

... 或用簡寫

class Block extends Component {
  shouldComponentUpdate = () => false;
}

有了這個生命週期掛鉤,並告訴 Preact 在 VDOM 樹發生變更時不要重新渲染元件,你的元件現在有一個可以被視為靜態的根 DOM 元素參考,直到元件被卸載。與任何元件一樣,這個參考只稱為 this.base,並且對應於從 render() 回傳的根 JSX 元素。


範例演練

以下是「關閉」元件重新渲染的範例。請注意,render() 仍會在建立和掛載元件時被呼叫,以產生其初始 DOM 結構。

class Example extends Component {
  shouldComponentUpdate() {
    // do not re-render via diff:
    return false;
  }

  componentWillReceiveProps(nextProps) {
    // you can do something with incoming props here if you need
  }

  componentDidMount() {
    // now mounted, can freely modify the DOM:
    let thing = document.createElement('maybe-a-custom-element');
    this.base.appendChild(thing);
  }

  componentWillUnmount() {
    // component is about to be removed from the DOM, perform any cleanup.
  }

  render() {
    return <div class="example" />;
  }
}

示範

demo

在 Webpackbin 上檢視此示範

真實世界的範例

或者,在 preact-token-input 中查看此技巧的實際應用 - 它使用元件作為 DOM 中的立足點,但隨後停用更新並讓 tags-input 從那裡接手。一個更複雜的範例是 preact-richtextarea,它使用此技巧來避免重新渲染可編輯的 <iframe>