docs(record): add bilingual usage guides
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: 嵌套上下文与稳定标识
|
||||
description: 组合局部记录上下文,并为记录列表选择稳定的 React key。
|
||||
order: 20
|
||||
toc:
|
||||
- id: nested-records
|
||||
title: 嵌套记录
|
||||
- id: optional-provider
|
||||
title: 可选 Provider
|
||||
- id: stable-keys
|
||||
title: 稳定标识
|
||||
---
|
||||
|
||||
## 嵌套记录 {#nested-records}
|
||||
|
||||
Provider 可以嵌套。内层字段读取局部记录,离开内层边界后恢复外层记录。
|
||||
|
||||
```tsx
|
||||
<RecordProvider value={order}>
|
||||
<OrderNumber />
|
||||
|
||||
<RecordProvider value={order.customer}>
|
||||
<CustomerName />
|
||||
</RecordProvider>
|
||||
</RecordProvider>
|
||||
```
|
||||
|
||||
不要把记录上下文当作可变 Store。新数据到达时,把新的记录引用传给 Provider;需要编辑的字段交给表单或其他状态层管理。
|
||||
|
||||
## 可选 Provider {#optional-provider}
|
||||
|
||||
`OptionalRecordProvider` 只在 `value` 不是 `undefined` 或 `null` 时创建新边界。值为空时,它保留最近的父级记录;`0`、`false` 和空字符串仍会创建新边界。这适合既能接收 prop、又能嵌入现有记录界面的组件。
|
||||
|
||||
```tsx
|
||||
function ProductCard({ product }: { product?: Product }) {
|
||||
return (
|
||||
<OptionalRecordProvider value={product}>
|
||||
<ProductTitle />
|
||||
<ProductPrice />
|
||||
</OptionalRecordProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## 稳定标识 {#stable-keys}
|
||||
|
||||
`RecordsIterator` 会直接使用字符串、数字或 bigint 记录作为 key;对于对象记录,它默认读取 `id`。其他值或没有 `id` 的对象可通过回调提供 `recordKey`,对象也可以提供字段名。只有未获得有效标识时才会回退到数组下标。
|
||||
|
||||
```tsx
|
||||
<RecordsIterator
|
||||
data={locales}
|
||||
iterator={(locale) => <LocaleRow />}
|
||||
recordKey="code"
|
||||
/>
|
||||
|
||||
<RecordsIterator
|
||||
data={revisions}
|
||||
recordKey={(revision) => `${revision.documentId}:${revision.version}`}
|
||||
>
|
||||
<RevisionRow />
|
||||
</RecordsIterator>
|
||||
```
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
title: 记录列表示例
|
||||
description: 使用共享字段组件渲染带上下文的记录列表。
|
||||
order: 30
|
||||
toc:
|
||||
- id: define-field-components
|
||||
title: 定义字段组件
|
||||
- id: render-the-list
|
||||
title: 渲染列表
|
||||
- id: iterator-callback
|
||||
title: 使用迭代回调
|
||||
- id: add-separators
|
||||
title: 添加分隔内容
|
||||
---
|
||||
|
||||
## 定义字段组件 {#define-field-components}
|
||||
|
||||
字段组件只依赖记录上下文,可以复用于详情页、列表和嵌套对象。
|
||||
|
||||
```tsx
|
||||
function ProductName() {
|
||||
const name = useFieldValue<Product, "name">({ source: "name" })
|
||||
return <strong>{name}</strong>
|
||||
}
|
||||
|
||||
function ProductPrice() {
|
||||
const price = useFieldValue<Product, "price">({ source: "price" })
|
||||
return <span>¥{price}</span>
|
||||
}
|
||||
```
|
||||
|
||||
## 渲染列表 {#render-the-list}
|
||||
|
||||
把相同的 children 传给 Iterator,它会为每条记录重新提供一次上下文。
|
||||
|
||||
```tsx
|
||||
<ul>
|
||||
<RecordsIterator data={products}>
|
||||
<li>
|
||||
<ProductName />
|
||||
<ProductPrice />
|
||||
</li>
|
||||
</RecordsIterator>
|
||||
</ul>
|
||||
```
|
||||
|
||||
当 `data` 为空、未定义,或没有提供 children/iterator 时,Iterator 返回 `null`。加载、错误和空状态由外层请求界面处理。
|
||||
|
||||
## 使用迭代回调 {#iterator-callback}
|
||||
|
||||
简单场景可以直接读取回调参数。回调仍然位于对应记录的上下文中,因此内部组件可以继续使用 Hooks。
|
||||
|
||||
```tsx
|
||||
<RecordsIterator
|
||||
data={products}
|
||||
iterator={(product, index) => (
|
||||
<article>
|
||||
<span>#{index + 1}</span>
|
||||
<ProductName />
|
||||
<button onClick={() => addToCart(product.id)}>Add</button>
|
||||
</article>
|
||||
)}
|
||||
/>
|
||||
```
|
||||
|
||||
## 添加分隔内容 {#add-separators}
|
||||
|
||||
使用 `separator` 在相邻记录之间插入分隔内容。它不会在第一条记录之前或最后一条记录之后渲染。回调参数是分隔符后面那条记录的索引,并且分隔内容位于对应记录的 `RecordProvider` 之外。
|
||||
|
||||
```tsx
|
||||
<RecordsIterator
|
||||
data={products}
|
||||
separator={(index) => <hr aria-label={`第 ${index} 个分隔符`} />}
|
||||
>
|
||||
<ProductCard />
|
||||
</RecordsIterator>
|
||||
```
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
title: 提供并读取记录
|
||||
description: 使用 RecordProvider、useRecord 和 useFieldValue 构建记录感知组件。
|
||||
order: 10
|
||||
toc:
|
||||
- id: provide-a-record
|
||||
title: 提供记录
|
||||
- id: read-a-record
|
||||
title: 读取记录
|
||||
- id: read-a-field
|
||||
title: 读取字段
|
||||
---
|
||||
|
||||
## 提供记录 {#provide-a-record}
|
||||
|
||||
在获得数据的边界挂载 Provider。`RecordProvider` 接受已经存在的非空记录;请求结果可能为空时,使用 `OptionalRecordProvider`。
|
||||
|
||||
```tsx
|
||||
import { RecordProvider } from "@workspace/record"
|
||||
|
||||
function ProductScreen({ product }: { product: Product }) {
|
||||
return (
|
||||
<RecordProvider value={product}>
|
||||
<ProductDetails />
|
||||
</RecordProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```tsx
|
||||
import { OptionalRecordProvider } from "@workspace/record"
|
||||
|
||||
;<OptionalRecordProvider value={query.data}>
|
||||
<ProductDetails />
|
||||
</OptionalRecordProvider>
|
||||
```
|
||||
|
||||
## 读取记录 {#read-a-record}
|
||||
|
||||
`useRecord` 在没有 Provider 或数据尚未加载时返回 `undefined`。
|
||||
|
||||
```tsx
|
||||
function ProductDetails() {
|
||||
const product = useRecord<Product>()
|
||||
if (!product) return <p>Loading…</p>
|
||||
|
||||
return <h2>{product.name}</h2>
|
||||
}
|
||||
```
|
||||
|
||||
记录感知组件也可以接受可选的 `record` prop。显式记录优先于上下文,方便单独预览和测试组件。
|
||||
|
||||
```tsx
|
||||
function ProductTitle({ record }: { record?: Product }) {
|
||||
const product = useRecord({ record })
|
||||
return product ? <h2>{product.name}</h2> : null
|
||||
}
|
||||
```
|
||||
|
||||
## 读取字段 {#read-a-field}
|
||||
|
||||
`useFieldValue` 支持直接字段、嵌套对象和数组数字段。路径使用点分隔。
|
||||
|
||||
```tsx
|
||||
const city = useFieldValue<Customer, "address.city">({
|
||||
source: "address.city",
|
||||
defaultValue: "Unknown",
|
||||
})
|
||||
|
||||
const firstSku = useFieldValue<Order, "items.0.sku">({
|
||||
source: "items.0.sku",
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: 概览
|
||||
description: 了解 Record 包如何在数据驱动界面中传递当前记录。
|
||||
order: 1
|
||||
toc:
|
||||
- id: package-role
|
||||
title: 包的职责
|
||||
- id: capabilities
|
||||
title: 主要能力
|
||||
- id: design-boundary
|
||||
title: 设计边界
|
||||
---
|
||||
|
||||
## 包的职责 {#package-role}
|
||||
|
||||
`@workspace/record` 是一个无 UI 的 React 记录上下文层。这里的“记录”不是特定对象类型:除 `undefined` 和 `null` 外,数字、布尔值、字符串、数组、函数和普通对象都可以作为记录。它让后代组件读取当前值,而不需要逐层传递 `record` prop。
|
||||
|
||||
## 主要能力 {#capabilities}
|
||||
|
||||
- 使用 `RecordProvider` 提供当前记录。
|
||||
- 使用 `useRecord` 读取上下文,或通过显式记录覆盖上下文。
|
||||
- 使用 `useFieldValue` 按类型安全的点路径读取嵌套字段。
|
||||
- 使用 `RecordsIterator` 为列表中的每条数据创建隔离的记录上下文。
|
||||
- 使用 `OptionalRecordProvider` 让组件同时支持独立使用和上下文组合。
|
||||
|
||||
## 设计边界 {#design-boundary}
|
||||
|
||||
该包不负责请求、缓存、分页、表单状态或 UI。请求层只需把已加载的值交给 Provider 或 Iterator。`undefined` 和 `null` 表示没有可提供的记录;`0`、`false` 和空字符串仍是有效记录。表单中的实时输入值仍应由表单状态读取。
|
||||
Reference in New Issue
Block a user