场景:点击表格操作栏中的移动行按钮,实现表格行的移动。也就是两行数据的交换。第一行提示最顶部无法上移,最后一行提示无法下移。
一、使用 useSelector 获取到列表数据,传给 Antd 表格组件的 dataSource
const { projectList } = useSelector(state => state.project);
// 获取列表数据
const getProjectList = () => {
dispatch({
type: 'project/getProjectList',
payload: { pageNo, pageSize, ...searchInfo }
});
}
<Table
rowKey='projectId'
columns={columns}
dataSource={projectList}
pagination={pagination}
/>
二、设置表格的 columns 属性
这里render
函数有第三个参数index
,可获取到表格行序号。CSS 实现两个按钮上下排列。
const columns = [
...
{
key: 'action',
title: '操作',
width: 150,
render: (text, record, index) => {
return (
<Fragment>
<span
className='ht-action-span'
style={{ position: 'relative', width: '14px', height: '25px', display: 'inline-block' }}>
<CaretUpOutlined
style={{
color: index === 0 ? 'gray' : '',
position: 'absolute', top: '8px'
}}
onClick={() => up(index, record)} />
<CaretDownOutlined
style={{
color: index === projectList.length - 1 ? 'gray' : '',
position: 'absolute', top: '20px'
}}
onClick={() => down(index, record)} />
</span>
<span
className='ht-action-span'
style={{ margin: "0 8px" }}
onClick={() => editProject(record)}>
<EditOutlined />
</span>
<span
className='ht-action-span'
onClick={() => deleteProject(record.projectId)}>
<DeleteOutlined />
</span>
</Fragment>
)
}
}
];
三、columns 操作列有上下移动两个按钮,给它们绑定点击事件
这里通过reducer
改变数据,实现移动。
之前通过setState
设置了一个表格的数据源,结果造成首次进入页面表格数据为空,需要再点一下数据才出现,而且编辑等也不能自动刷新页面数据。
打印发现useSelector
有延迟的效果,会给你返回多个projectList
,但是前几个是空数组。
const up = (index, record) => {
if (index === 0) {
return message.warning("最顶部无法上移");
}
let list = projectList;
// let prev = list[index - 1];
// list.splice(index - 1, 1);
// list.splice(index, 0, prev);
// 使用 ES6 优化
[list[index - 1], list[index]] = [list[index], list[index - 1]];
dispatch({
type: 'project/setProjectList',
payload: {
projectList: [...list]
}
})
}
const down = (index, record) => {
if (index === projectList.length - 1) {
return message.warning("最底部无法下移");
}
// let next = projectList[index + 1];
// projectList.splice(index + 1, 1);
// projectList.splice(index, 0, next);
let list = projectList;
[list[index], list[index - 1]] = [list[index - 1], list[index]];
dispatch({
type: 'project/setProjectList',
payload: {
projectList: [...list]
}
})
}
四、dva-loading
实践用法
dva-loading
用于监听当前异步加载方法的状态,异步加载中状态为true
,异步加载完成状态为false
。
const isLoading = loading.effects['user/query'];
其中user/query
是 model 中的异步请求方法。loading
在异步请求发出那一刻会持续监听该异步请求方法的状态,在异步请求结束之前isLoading
的值一直是true
,当此次异步请求结束时isLoading
的值变成false
,同时loading
对象停止监听。
用法一:在 Antd 的Table 组件
中使用loading
属性判断当前是否有异步加载,显示加载效果。
import React from 'react';
import { Table } from 'antd';
import { useDispatch, useSelector } from 'dva';
const Project = () => {
const dispatch = useDispatch();
const { projectList } = useSelector(state => state.project);
const loading = useSelector(state => state.loading.effects['project/getProjectList']);
// 获取列表数据
const getProjectList = () => {
dispatch({
type: 'project/getProjectList',
payload: { pageNo, pageSize, ...searchInfo }
});
}
return (
<Table
rowKey='projectId'
columns={columns}
dataSource={projectList}
pagination={pagination}
loading={loading}
/>
)
}
export default Project;
用法二:提交按钮如登录等使用loading
控制effects
提交路径。
const loading = useSelector(state => state.loading.effects);
<Button
type="primary"
htmlType="submit"
loading={loading['auth/login']}
>
登录
</Button>