外部 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" />;
}
}
演示
真实世界示例
或者,在 preact-token-input 中查看此技术的实际应用 - 它使用组件作为 DOM 中的立足点,但随后禁用更新并让 tags-input 从那里接管。一个更复杂的示例是 preact-richtextarea,它使用此技术来避免重新渲染可编辑的 <iframe>
。