切换到 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 核心之上提供了所有必要的调整,使其在单个模块中像 reactreact-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,你需要将 reactreact-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 the render 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, whereas shouldComponentUpdate 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 (experimental)

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.

此功能是实验性的,可能包含错误。我们将其作为早期预览版提供,以提高测试可见性。我们不建议在生产中使用它。

¥This feature is experimental and may contain bugs. We have included it as an early preview to increase testing visibility. We don't recommend using it in production.

Preact 中文网 - 粤ICP备13048890号