静态结构创建
筛选区结构搭建
- 如何让 RangePicker 日期范围选择框选择中文
- Select 组件配合 Form.Item 使用时,如何配置默认选中项
代码实现
pages/Article/index.jsx
jsx
import {
Breadcrumb,
Button,
Form,
Input,
Select,
message,
Radio,
Divider,
DatePicker,
} from "antd";
import {
HomeOutlined,
ContainerOutlined,
SearchOutlined,
} from "@ant-design/icons";
import { useEffect, useState } from "react";
import locale from "antd/es/date-picker/locale/zh_CN";
const Article = () => {
const { RangePicker } = DatePicker;
// 频道列表
const [channels, setChannels] = useState([]);
return (
<div className="Article">
{/* 面包屑导航 */}
<Breadcrumb
items={[
{
title: (
<>
<HomeOutlined />
<span>首页</span>
</>
),
},
{
title: (
<>
<ContainerOutlined />
<span>文章列表</span>
</>
),
},
]}
/>
<Divider />
{/* 搜索项 */}
<Form initialValues={{ status: "" }} autoComplete="off" layout="inline">
<Form.Item label="状态" name="status">
<Radio.Group>
<Radio value={""}> 全部 </Radio>
<Radio value={0}> 草稿 </Radio>
<Radio value={2}> 审核通过 </Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="频道" name="channel_id">
<Select showSearch placeholder="请选择频道" optionFilterProp="label">
{channels.map((item) => (
<Select.Option key={item.id} value={item.id}>
{item.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label="日期" name="date">
{/* 传入locale属性 控制中文显示*/}
<RangePicker locale={locale}></RangePicker>
</Form.Item>
<Form.Item>
<Button type="primary" icon={<SearchOutlined />} htmlType="submit">
查询
</Button>
</Form.Item>
</Form>
</div>
);
};
export default Article;
表格区域结构
代码实现
jsx
// 导入资源
import { Table, Tag, Space } from "antd";
import { EditOutlined, DeleteOutlined } from "@ant-design/icons";
import img404 from "@/assets/error.png";
const Article = () => {
// 准备列数据
const columns = [
{
title: "封面",
dataIndex: "cover",
width: 120,
render: (cover) => {
return (
<img src={cover.images[0] || img404} width={80} height={60} alt="" />
);
},
},
{
title: "标题",
dataIndex: "title",
width: 220,
},
{
title: "状态",
dataIndex: "status",
render: (data) => <Tag color="green">审核通过</Tag>,
},
{
title: "发布时间",
dataIndex: "pubdate",
},
{
title: "阅读数",
dataIndex: "read_count",
},
{
title: "评论数",
dataIndex: "comment_count",
},
{
title: "点赞数",
dataIndex: "like_count",
},
{
title: "操作",
render: (data) => {
return (
<Space size="middle">
<Button type="primary" shape="circle" icon={<EditOutlined />} />
<Button
type="primary"
danger
shape="circle"
icon={<DeleteOutlined />}
/>
</Space>
);
},
},
];
// 准备表格body数据
const data = [
{
id: "8218",
comment_count: 0,
cover: {
images: [],
},
like_count: 0,
pubdate: "2019-03-11 09:00:00",
read_count: 2,
status: 2,
title: "wkwebview离线化加载h5资源解决方案",
},
];
return (
<div>
...
<Table rowKey="id" columns={columns} dataSource={data} />
</div>
);
};
获取频道数据
自定义 Hooks 是一个函数,其名称以 use 开头,函数内部可以调用 React 的 Hooks,也可以返回一些数据给调用者。
实现步骤
- 创建
useChannel.js
文件,封装获取频道列表的逻辑 - 在列表页中引入
useChannel.js
文件 - 解构
hooks
,获取频道列表数据
代码实现
jsx
// 封装获取频道列表的逻辑
import { useState, useEffect } from "react";
import http from "@/utils/http";
export default function useChannel() {
const [channelList, setChannelList] = useState([]);
useEffect(() => {
function getChannelList() {
http.get("/channels").then((res) => {
setChannelList(res.data.channels);
});
}
getChannelList();
}, []);
return { channelList, setChannelList };
}
jsx
import useChannel from "@/hooks/useChannel";
const Article = () => {
const { channelList } = useChannel();
return (
...
<Form.Item label="频道" name="channel_id">
<Select
showSearch
placeholder="请选择频道"
optionFilterProp="label"
style={{ width: 180 }}
>
{channelList.map((item) => (
<Select.Option key={item.id} value={item.id}>
{item.name}
</Select.Option>
))}
</Select>
</Form.Item>
);
};
渲染表格数据
实现步骤
- 声明列表相关数据管理
- 使用 useState 声明参数相关数据管理
- 调用接口获取数据
- 使用接口数据渲染模板
代码实现
jsx
const Article = () => {
// 省略部分代码...
// 文章列表数据管理
const [article, setArticleList] = useState({
list: [],
count: 0,
});
const [params, setParams] = useState({
page: 1,
per_page: 4,
begin_pubdate: null,
end_pubdate: null,
status: null,
channel_id: null,
});
// 获取文章列表
const fetchArticleList = () => {
http.get("/mp/articles", { params }).then((res) => {
const { results, total_count } = res.data;
console.log('results', res.data);
setArticleList({
list: results,
count: total_count
})
})
}
useEffect(() => {
fetchArticleList()
}, [params])
// 模板渲染
return (
...
{/* 表格 */}
<Table rowKey="id" columns={columns} dataSource={articleList.list} scroll={{ y: 550 }} />
);
};
笔记
useEffect
会根据依赖性params
的变化触发,当依赖项发生变化时,useEffect
中的函数会重新执行。
渲染审批状态
实现步骤
- 定义审核状态枚举
- 渲染状态数据
jsx
import { Tag } from "antd";
const Article = () => {
// 定义审核状态枚举
const statusMap = {
0: <Tag color="info">草稿</Tag>,
1: <Tag color="primary">待审核</Tag>,
2: <Tag color="success">审核通过</Tag>,
3: <Tag color="warning">审核失败</Tag>,
}
// 准备列数据
const columns = [
...
{
title: '状态',
dataIndex: 'status',
render: data => statusMap[data]
}
]
return (
)
}
筛选功能实现
实现步骤
- 使用
useState
管理查询参数 - 当参数变化时,
useEffect
会触发fetchArticleList
函数查询列表 - 提供了
onSearch
函数来处理搜索条件的更新
代码实现
jsx
import { useEffect, useState } from "react";
import http from "@/utils/http";
const Article = () => {
const [params, setParams] = useState({page: 1, per_page: 6, begin_pubdate: null, end_pubdate: null, status: null, channel_id: null,})
// 搜索
const onSearch = values => {
console.log(values);
const { status, channel_id, date } = values
setParams(
{
...params,
status, channel_id,
begin_pubdate: date && date[0].format("YYYY-MM-DD"),
end_pubdate: date && date[1].format("YYYY-MM-DD"),
}
)
};
// 获取文章列表
const fetchArticleList = () => {
http.get("/mp/articles", { params }).then((res) => {
const { results, total_count } = res.data;
console.log('results', res.data);
setArticleList({
list: results,
count: total_count
})
})
}
useEffect(() => {
fetchArticleList()
}, [params])
}
分页功能实现
实现步骤
- 为 Table 组件指定
pagination
属性来展示分页效果 - 在分页切换事件中获取到筛选表单中选中的数据
- 修改 params 参数依赖引起接口重新调用获取最新数据
- 通过
showTotal
属性来指定分页的显示格式
代码实现
jsx
const pageChange = (page) => {
// 拿到当前页参数 修改params引起接口更新
setParams({
...params,
page,
});
};
return (
<Table
rowKey="id"
columns={columns}
dataSource={article.list}
pagination={{
current: params.page,
pageSize: params.per_page,
onChange: pageChange,
total: article.count,
showTotal: (total) => `共 ${total} 条数据`,
}}
/>
);
删除功能
实现步骤
- 创建
delArticle
函数,删除文章 - 删除成功后,重新获取文章列表数据
代码实现
jsx
// 删除回调
const delArticle = async (data) => {
await http.delete(`/mp/articles/${data.id}`)
// 更新列表
setParams({
page: 1,
per_page: 10
})
}
const columns = [
// ...
{
title: '操作',
render: data => {
return (
<Space size="middle">
<Button type="primary" shape="circle" icon={<EditOutlined />} />
<Popconfirm
title="确认删除该条文章吗?"
onConfirm={() => delArticle(data)}
okText="确认"
cancelText="取消"
>
<Button
type="primary"
danger
shape="circle"
icon={<DeleteOutlined />}
/>
</Popconfirm>
</Space>
)
}
]
编辑文章跳转
实现步骤
- 给编辑按钮绑定点击事件
- 使用
navagite
跳转到编辑页面
代码实现
jsx
const navigate = useNavigate()
const columns = [
// ...
{
title: "操作",
render: (data) => (
<Space size="middle">
<Button
type="primary"
shape="circle"
icon={<EditOutlined />}
onClick={() => navagite(`/publish?id=${data.id}`)}
/>
/>
</Space>
),
},
];