175 lines
4.7 KiB
Markdown
175 lines
4.7 KiB
Markdown
---
|
||
name: "search-state-persistence"
|
||
description: "Search state persistence via tools.router.query. Invoke when implementing search/table pages with SearchForm + Table + pagination that need to preserve query params across refreshes."
|
||
---
|
||
|
||
# 搜索状态持久化
|
||
|
||
通过 `tools.router.query` 实现搜索条件持久化,刷新页面后搜索条件和分页状态保留在 URL 查询参数中。
|
||
|
||
## 核心 API
|
||
|
||
```js
|
||
import { tools } from "@cqsjjb/jjb-common-lib";
|
||
const { router } = tools;
|
||
```
|
||
|
||
`router.query` 是一个响应式对象,对其赋值会同步更新 URL 查询参数。
|
||
|
||
## 完整模式
|
||
|
||
```jsx
|
||
import React, { useState, useEffect } from "react";
|
||
import { Button, Form, Select, Space, Table, Tag } from "antd";
|
||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||
import SearchForm from "~/components/SearchForm";
|
||
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
|
||
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
||
import { tools } from "@cqsjjb/jjb-common-lib";
|
||
|
||
const { router } = tools;
|
||
|
||
const MyPage = (props) => {
|
||
const [form] = Form.useForm();
|
||
const [loading, setLoading] = useState(false);
|
||
|
||
/** 搜索/刷新数据 */
|
||
const handleSearch = () => {
|
||
setLoading(true);
|
||
// 实际请求...
|
||
setTimeout(() => setLoading(false), 500);
|
||
};
|
||
|
||
/** 重置搜索 */
|
||
const handleReset = (values) => {
|
||
router.query = {
|
||
...router.query,
|
||
...values,
|
||
current: 1,
|
||
size: 10,
|
||
};
|
||
handleSearch();
|
||
};
|
||
|
||
/** 初始化:将 URL 中的查询条件回填到表单 */
|
||
useEffect(() => {
|
||
form.setFieldsValue(router.query);
|
||
}, []);
|
||
|
||
const columns = [
|
||
// ...列定义
|
||
];
|
||
|
||
return (
|
||
<PageLayout title="页面标题">
|
||
<SearchForm
|
||
style={{ marginBottom: 24 }}
|
||
form={form}
|
||
loading={loading}
|
||
formLine={[
|
||
<Form.Item key="fieldName" name="fieldName">
|
||
<ControlWrapper.Input label="字段名" placeholder="请输入" allowClear />
|
||
</Form.Item>,
|
||
]}
|
||
onReset={handleReset}
|
||
onFinish={(values) => {
|
||
router.query = {
|
||
...router.query,
|
||
...values,
|
||
current: 1,
|
||
size: 10,
|
||
};
|
||
handleSearch();
|
||
}}
|
||
/>
|
||
|
||
<Table
|
||
rowKey="id"
|
||
columns={columns}
|
||
dataSource={data}
|
||
scroll={{ y: props.scrollY }}
|
||
loading={loading}
|
||
pagination={{
|
||
total: total,
|
||
showSizeChanger: true,
|
||
showQuickJumper: true,
|
||
showTotal: (total) => `共 ${total} 条`,
|
||
current: router.query.current,
|
||
pageSize: router.query.size,
|
||
onChange: (page, pageSize) => {
|
||
router.query = {
|
||
...router.query,
|
||
current: page,
|
||
size: pageSize,
|
||
};
|
||
handleSearch();
|
||
},
|
||
}}
|
||
/>
|
||
</PageLayout>
|
||
);
|
||
};
|
||
|
||
export default AntdTableFuncControl(MyPage);
|
||
```
|
||
|
||
## 关键规则
|
||
|
||
### 1. 初始化回填
|
||
在 `useEffect` 中将 `router.query` 的值回填到表单,确保刷新后表单显示与 URL 一致:
|
||
```js
|
||
useEffect(() => {
|
||
form.setFieldsValue(router.query);
|
||
}, []);
|
||
```
|
||
|
||
**注意**:`router.query` 中所有值均为字符串,而 `DatePicker` / `RangePicker` 需要 `dayjs` 对象。当表单包含日期字段时,必须手动转换:
|
||
```js
|
||
useEffect(() => {
|
||
searchForm.setFieldsValue({
|
||
...router.query,
|
||
dateRange:
|
||
router.query.startTime && router.query.endTime
|
||
? [dayjs(router.query.startTime), dayjs(router.query.endTime)]
|
||
: undefined,
|
||
});
|
||
}, []);
|
||
```
|
||
|
||
### 2. 搜索/重置写入
|
||
搜索提交(`onFinish`) 和重置(`onReset`) 时,将表单值与默认分页合并写入 `router.query`:
|
||
```js
|
||
router.query = {
|
||
...router.query,
|
||
...values, // 表单值
|
||
current: 1, // 重置到第一页
|
||
pageSize: 10, // 默认页大小
|
||
};
|
||
```
|
||
|
||
### 3. 翻页写入
|
||
分页变化时,仅更新 `current` 和 `pageSize`,保留已有搜索条件:
|
||
```js
|
||
onChange: (page, pageSize) => {
|
||
router.query = {
|
||
...router.query, // 保留已有搜索条件
|
||
current: page,
|
||
pageSize,
|
||
};
|
||
handleSearch();
|
||
};
|
||
```
|
||
|
||
### 4. 组件装饰器
|
||
页面组件必须用 `AntdTableFuncControl` 包裹以支持表格功能:
|
||
```js
|
||
export default AntdTableFuncControl(MyPage);
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
- `router.query` 是响应式的:赋值会触发 URL 更新,且刷新后值仍然保留
|
||
- `router.query` 中所有值均为字符串类型(URL query 的特性),使用 `current` 和 `pageSize` 时注意隐式类型转换
|
||
- 默认值 `current: 1, pageSize: 10` 是约定,可根据实际需求修改
|
||
- `onReset` 回调的 `values` 参数是重置后的表单值(所有字段清空/恢复默认后的值)
|