从 React 切换到 Preact
preact/compat
是我们的兼容性层,它允许你利用 React 生态系统的众多库,并将其与 Preact 一起使用。如果你有现有的 React 应用程序,这是尝试 Preact 的推荐方法。
这让你可以继续编写 React/ReactDOM 代码,而无需更改你的工作流或代码库。preact/compat
会为你的包大小增加大约 2kb,但它有支持你可能在 npm 上找到的绝大多数现有 React 模块的优势。preact/compat
包在 Preact 核心之上提供了所有必要的调整,使其在单个模块中像 react
和 react-dom
一样工作。
设置兼容性
要设置 preact/compat
,你需要将 react
和 react-dom
别名为 preact/compat
。入门页面详细介绍了如何在各种打包器中配置别名。
PureComponent
PureComponent
类与 Component
类似。不同之处在于,当新道具与旧道具相等时,PureComponent
将跳过渲染。为此,我们通过浅层比较旧道具和新道具,检查每个道具属性的引用相等性。通过避免不必要的重新渲染,这可以极大地加速应用程序。它通过添加一个默认的 shouldComponentUpdate
生命周期挂钩来工作。
import { render } from 'preact';
import { PureComponent } from 'preact/compat';
class Foo extends PureComponent {
render(props) {
console.log("render")
return <div />
}
}
const dom = document.getElementById('root');
render(<Foo value="3" />, dom);
// Logs: "render"
// Render a second time, doesn't log anything
render(<Foo value="3" />, dom);
请注意,
PureComponent
的优势只有在渲染开销很大时才会显现。对于简单的子树,与比较道具的开销相比,直接进行render
可能更快。
memo
memo
等效于函数组件,就像 PureComponent
等效于类。它在底层使用相同的比较函数,但允许你指定针对你的用例优化的自己的专门函数。
import { memo } from 'preact/compat';
function MyComponent(props) {
return <div>Hello {props.name}</div>
}
// Usage with default comparison function
const Memoed = memo(MyComponent);
// Usage with custom comparison function
const Memoed2 = memo(MyComponent, (prevProps, nextProps) => {
// Only re-render when `name' changes
return prevProps.name === nextProps.name;
})
比较函数不同于
shouldComponentUpdate
,因为它检查两个道具对象是否 相等,而shouldComponentUpdate
检查它们是否不同。
forwardRef
在某些情况下,编写组件时,您希望允许用户获取树中更深层次的特定引用。使用 forwardRef
,您可以“转发”ref
属性
import { createRef, render } from 'preact';
import { forwardRef } from 'preact/compat';
const MyComponent = forwardRef((props, ref) => {
return <div ref={ref}>Hello world</div>;
})
// Usage: `ref` will hold the reference to the inner `div` instead of
// `MyComponent`
const ref = createRef();
render(<MyComponent ref={ref} />, dom)
此组件对库作者非常有用。
门户
在极少数情况下,您可能希望继续呈现到不同的 DOM 节点。目标 DOM 节点必须在尝试呈现到其中之前存在。
<html>
<body>
<!-- App is rendered here -->
<div id="app"></div>
<!-- Modals should be rendered here -->
<div id="modals"></div>
</body>
</html>
import { createPortal } from 'preact/compat';
import MyModal from './MyModal';
function App() {
const container = document.getElementById('modals');
return (
<div>
I'm app
{createPortal(<MyModal />, container)}
</div>
)
}
请记住,由于 Preact 重用了浏览器的事件系统,因此事件不会通过门户容器冒泡到另一棵树。
Suspense(实验性)
Suspense
背后的主要思想是允许 UI 的部分显示某种占位符内容,而树中更深层次的组件仍在加载。一个常见的用例是代码拆分,在代码拆分中,您需要从网络加载组件才能呈现它。
import { Suspense, lazy } from 'preact/compat';
const SomeComponent = lazy(() => import('./SomeComponent'));
// Usage
<Suspense fallback={<div>loading...</div>}>
<Foo>
<SomeComponent />
</Foo>
</Suspense>
在此示例中,UI 将显示 loading...
文本,直到加载 SomeComponent
并且 Promise 已解决。
此功能为实验性功能,可能包含错误。我们已将其作为早期预览包含在内,以提高测试可见性。我们不建议在生产中使用它。