切换到 Preact(从 React)
¥Switching to Preact (from React)
preact/compat
是我们的兼容层,允许你利用 React 生态系统的许多库并将它们与 Preact 一起使用。如果你有现有的 React 应用,这是尝试 Preact 的推荐方法。
¥preact/compat
is our compatibility layer that allows you to leverage the many libraries of the React ecosystem and use them with Preact. This is the recommended way to try out Preact if you have an existing React app.
这使你可以继续编写 React/ReactDOM 代码,而无需对工作流程或代码库进行任何更改。preact/compat
使你的包大小增加了大约 2kb,但具有支持你可能在 npm 上找到的绝大多数现有 React 模块的优势。preact/compat
包在 Preact 核心之上提供了所有必要的调整,使其在单个模块中像 react
和 react-dom
一样工作。
¥This lets you continue writing React/ReactDOM code without any changes to your workflow or codebase. preact/compat
adds somewhere around 2kb to your bundle size, but has the advantage of supporting the vast majority of existing React modules you might find on npm. The preact/compat
package provides all the necessary tweaks on top of Preact's core to make it work just like react
and react-dom
, in a single module.
设置兼容
¥Setting up compat
要设置 preact/compat
,你需要将 react
和 react-dom
别名为 preact/compat
。入门 页面详细介绍了如何在各种打包器中配置别名。
¥To set up preact/compat
you need to alias react
and react-dom
to preact/compat
. The Getting Started page goes into detail on how aliasing is configured in various bundlers.
PureComponent
PureComponent
类的工作方式与 Component
类似。不同的是,当新的 props 与旧的 props 相等时,PureComponent
会跳过渲染。为此,我们通过浅层比较来比较新旧 props,其中我们检查每个 props 属性的引用相等性。这可以通过避免不必要的重新渲染来大大加快应用的速度。它的工作原理是添加默认的 shouldComponentUpdate
生命周期钩子。
¥The PureComponent
class works similar to Component
. The difference is that PureComponent
will skip rendering when the new props are equal to the old ones. To do this we compare the old and new props via a shallow comparison where we check each props property for referential equality. This can speed up applications a lot by avoiding unnecessary re-renders. It works by adding a default shouldComponentUpdate
lifecycle hook.
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
的优势才会发挥作用。对于简单的子树,与比较 props 的开销相比,仅执行render
会更快。¥Note that the advantage of
PureComponent
only pays off when then render is expensive. For simple children trees it can be quicker to just do therender
compared to the overhead of comparing props.
memo
memo
相当于功能组件,正如 PureComponent
相当于类。它在底层使用相同的比较函数,但允许你指定针对你的用例进行优化的专用函数。
¥memo
is equivalent to functional components as PureComponent
is to classes. It uses the same comparison function under the hood, but allows you to specify your own specialized function optimized for your use case.
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
的不同之处在于,它检查两个 props 对象是否相等,而shouldComponentUpdate
检查它们是否不同。¥The comparison function is different from
shouldComponentUpdate
in that it checks if the two props objects are equal, whereasshouldComponentUpdate
checks if they are different.
forwardRef
在某些情况下,当编写组件时,你希望允许用户获取树中更深处的特定引用。使用 forwardRef
,你可以对 "forward" 和 ref
属性进行排序:
¥In some cases when writing a component you want to allow the user to get hold of a specific reference further down the tree. With forwardRef
you can sort-of "forward" the ref
property:
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)
该组件对于库作者来说最有用。
¥This component is most useful for library authors.
门户网站
¥Portals
在极少数情况下,你可能希望继续渲染到不同的 DOM 节点。在尝试渲染到目标 DOM 节点之前,目标 DOM 节点必须存在。
¥In rare circumstances you may want to continue rendering into a different DOM node. The target DOM node must be present before attempting to render into it.
<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 重用浏览器的事件系统,事件不会通过 Portal 容器向上冒泡到另一棵树。
¥Keep in mind that due to Preact reusing the browser's event system, events won't bubble up through a Portal container to the other tree.
Suspense
Suspense
背后的主要思想是允许 UI 的各个部分显示某种占位符内容,同时树下方的组件仍在加载。一个常见的用例是代码分割,你需要从网络加载组件,然后才能渲染它。
¥The main idea behind Suspense
is to allow sections of your UI to display some sort of placeholder content while components further down the tree are still loading. A common use case for this is code-splitting where you'll need to load a component from the network before you can render it.
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。
¥In this example the UI will display the loading...
text until SomeComponent
is loaded and the Promise is resolved.
React 和 Preact 中的 Suspense 尚未完全完成或一成不变。虽然 React 团队仍然积极阻止用户直接与其交互以获取数据,但这是一些 Preact 用户在过去几年中一直乐于使用的模式。存在一些已知问题(请参阅 我们的跟踪器 以获取最新参考),但如果你愿意,它通常被认为足够稳定,可用于生产。
¥Suspense in both React and Preact isn't quite finalized or set in stone as of yet. While the React team still actively discourages users interfacing with it directly for data fetching, it's a pattern some Preact users have been happily using over the last few years. There are a few known issues (please see our tracker for an up-to-date reference) but it's generally considered stable enough for use in production if you so wish.
例如,此站点是使用基于 Suspense 的数据获取策略构建的,用于加载你看到的所有内容。
¥This site, for instance, is built using a Suspense-based data fetching strategy used to load all content you see.