Appearance
客户端组件
🌐 Client Components
hono/jsx 不仅支持服务器端,也支持客户端。这意味着可以创建在浏览器中运行的交互式用户界面。我们称之为客户端组件或 hono/jsx/dom。
它速度快且体积很小。hono/jsx/dom 中的计数器程序在 Brotli 压缩下仅为 2.8KB,而 React 则为 47.8KB。
🌐 It is fast and very small. The counter program in hono/jsx/dom is only 2.8KB with Brotli compression, but 47.8KB for React.
本节介绍客户端组件特有的功能。
🌐 This section introduces Client Components-specific features.
反例
🌐 Counter example
以下是简单计数器的示例,相同的代码与 React 中的工作方式相同。
🌐 Here is an example of a simple counter, the same code works as in React.
tsx
import { useState } from 'hono/jsx'
import { render } from 'hono/jsx/dom'
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
)
}
function App() {
return (
<html>
<body>
<Counter />
</body>
</html>
)
}
const root = document.getElementById('root')
render(<App />, root)render()
你可以使用 render() 在指定的 HTML 元素中插入 JSX 组件。
🌐 You can use render() to insert JSX components within a specified HTML element.
tsx
render(<Component />, container)你可以在这里看到完整的示例代码:Counter 示例。
🌐 You can see full example code here: Counter example.
与 React 兼容的 Hooks
🌐 Hooks compatible with React
hono/jsx/dom 有与 React 兼容或部分兼容的 Hooks。你可以通过查看 React 文档 来了解这些 API。
🌐 hono/jsx/dom has Hooks that are compatible or partially compatible with React. You can learn about these APIs by looking at the React documentation.
useState()useEffect()useRef()useCallback()use()startTransition()useTransition()useDeferredValue()useMemo()useLayoutEffect()useReducer()useDebugValue()createElement()memo()isValidElement()useId()createRef()forwardRef()useImperativeHandle()useSyncExternalStore()useInsertionEffect()useFormStatus()useActionState()useOptimistic()
startViewTransition() 家族
🌐 startViewTransition() family
startViewTransition() 家族包含原始的 hooks 和函数,用于轻松处理 View Transitions API。下面的示例演示了如何使用它们。
🌐 The startViewTransition() family contains original hooks and functions to handle View Transitions API easily. The examples below demonstrate how to use them.
1. 一个非常简单的例子
🌐 1. A very simple example
你可以使用 startViewTransition() 很快地写一个 document.startViewTransition 过渡。
🌐 You can write a transition using the document.startViewTransition shortly with the startViewTransition().
tsx
import { useState, startViewTransition } from 'hono/jsx'
import { css, Style } from 'hono/css'
export default function App() {
const [showLargeImage, setShowLargeImage] = useState(false)
return (
<>
<Style />
<button
onClick={() =>
startViewTransition(() =>
setShowLargeImage((state) => !state)
)
}
>
Click!
</button>
<div>
{!showLargeImage ? (
<img src='https://hono.nodejs.cn/images/logo.png' />
) : (
<div
class={css`
background: url('https://hono.nodejs.cn/images/logo-large.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 600px;
height: 600px;
`}
></div>
)}
</div>
</>
)
}2. 将 viewTransition() 与 keyframes() 一起使用
🌐 2. Using viewTransition() with keyframes()
viewTransition() 函数允许你获取唯一的 view-transition-name。
🌐 The viewTransition() function allows you to get the unique view-transition-name.
你可以将它与 keyframes() 一起使用,::view-transition-old() 被转换为 ::view-transition-old(${uniqueName))。
🌐 You can use it with the keyframes(), The ::view-transition-old() is converted to ::view-transition-old(${uniqueName)).
tsx
import { useState, startViewTransition } from 'hono/jsx'
import { viewTransition } from 'hono/jsx/dom/css'
import { css, keyframes, Style } from 'hono/css'
const rotate = keyframes`
from {
rotate: 0deg;
}
to {
rotate: 360deg;
}
`
export default function App() {
const [showLargeImage, setShowLargeImage] = useState(false)
const [transitionNameClass] = useState(() =>
viewTransition(css`
::view-transition-old() {
animation-name: ${rotate};
}
::view-transition-new() {
animation-name: ${rotate};
}
`)
)
return (
<>
<Style />
<button
onClick={() =>
startViewTransition(() =>
setShowLargeImage((state) => !state)
)
}
>
Click!
</button>
<div>
{!showLargeImage ? (
<img src='https://hono.nodejs.cn/images/logo.png' />
) : (
<div
class={css`
${transitionNameClass}
background: url('https://hono.nodejs.cn/images/logo-large.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 600px;
height: 600px;
`}
></div>
)}
</div>
</>
)
}3. 使用 useViewTransition
🌐 3. Using useViewTransition
如果你只想在动画期间更改样式,你可以使用 useViewTransition()。这个钩子返回 [boolean, (callback: () => void) => void],它们分别是 isUpdating 标志和 startViewTransition() 函数。
🌐 If you want to change the style only during the animation. You can use useViewTransition(). This hook returns the [boolean, (callback: () => void) => void], and they are the isUpdating flag and the startViewTransition() function.
使用此钩子时,组件将在以下两次进行评估。
🌐 When this hook is used, the Component is evaluated at the following two times.
- 在对
startViewTransition()的调用回调中。 - 当
finish承诺兑现时
tsx
import { useState, useViewTransition } from 'hono/jsx'
import { viewTransition } from 'hono/jsx/dom/css'
import { css, keyframes, Style } from 'hono/css'
const rotate = keyframes`
from {
rotate: 0deg;
}
to {
rotate: 360deg;
}
`
export default function App() {
const [isUpdating, startViewTransition] = useViewTransition()
const [showLargeImage, setShowLargeImage] = useState(false)
const [transitionNameClass] = useState(() =>
viewTransition(css`
::view-transition-old() {
animation-name: ${rotate};
}
::view-transition-new() {
animation-name: ${rotate};
}
`)
)
return (
<>
<Style />
<button
onClick={() =>
startViewTransition(() =>
setShowLargeImage((state) => !state)
)
}
>
Click!
</button>
<div>
{!showLargeImage ? (
<img src='https://hono.nodejs.cn/images/logo.png' />
) : (
<div
class={css`
${transitionNameClass}
background: url('https://hono.nodejs.cn/images/logo-large.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 600px;
height: 600px;
position: relative;
${isUpdating &&
css`
&:before {
content: 'Loading...';
position: absolute;
top: 50%;
left: 50%;
}
`}
`}
></div>
)}
</div>
</>
)
}hono/jsx/dom 运行时
🌐 The hono/jsx/dom runtime
有一个用于客户端组件的小型 JSX 运行时。使用它将比使用 hono/jsx 生成更小的打包结果。在 tsconfig.json 中指定 hono/jsx/dom。对于 Deno,请修改 deno.json。
🌐 There is a small JSX Runtime for Client Components. Using this will result in smaller bundled results than using hono/jsx. Specify hono/jsx/dom in tsconfig.json. For Deno, modify the deno.json.
json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx/dom"
}
}或者,你可以在 vite.config.ts 中的 esbuild 转换选项中指定 hono/jsx/dom。
🌐 Alternatively, you can specify hono/jsx/dom in the esbuild transform options in vite.config.ts.
ts
import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
jsxImportSource: 'hono/jsx/dom',
},
})