环境:"react": "^16.8.6",
???????????"react-sortable-hoc": "^2.0.0"
因项目中需要实现拖拽列,其他地方也需要使用所以单独封装成一个组件,方便其他地方调用。
先看成品:
功能是拖拽列前面ico图标可以上下替换
1、封装sortable组件
import React from "react";
import {
sortableContainer,
sortableElement,
sortableHandle,
} from "react-sortable-hoc"; // 拖拽的关键组件
import styled from "@emotion/styled"; // 设置局部css
const ListItem = styled.div`
display: flex;
min-height: 50px;
align-items: center;
background-color: #f5f5f5;
border-radius: 4px;
margin-bottom: 10px;
padding-left: 8px;
padding-right: 15px;
box-sizing: border-box;
z-index: 9999;
`;
const DrapIcon = styled.span`
padding-right: 8px;
cursor: move;
`;
const ChildCom = styled.div`
flex: 1;
`;
const DeleteBtn = styled.div`
color: #999;
font-size: 16px;
cursor: pointer;
`;
// 拖拽时原列表替换
function arrayMoveMutable(array, fromIndex, toIndex) {
const startIndex = fromIndex < 0 ? array.length + fromIndex : fromIndex;
if (startIndex >= 0 && startIndex < array.length) {
const endIndex = toIndex < 0 ? array.length + toIndex : toIndex;
const [item] = array.splice(fromIndex, 1);
array.splice(endIndex, 0, item);
}
}
// 拖拽时返回新数组
function arrayMoveImmutable(array, fromIndex, toIndex) {
array = [...array];
arrayMoveMutable(array, fromIndex, toIndex);
return array;
}
// 拖拽容器
const SortableContainer = sortableContainer(({ children }) => {
return <div>{children}</div>;
});
// 拖拽ico
const DragHandle = sortableHandle(() => (
<DrapIcon className="iconfont icon-tuozhuai"></DrapIcon>
));
function Sortable(props) {
const { dataSource=[], ComSortItem, sortEnd } = props;
function handleDelete(index) {
const List = [...dataSource];
List.splice(index,1)
sortEnd(List);
}
// 数据更新
function updateData(val,index) {
const List = [...dataSource];
List[index] = val;
sortEnd(List);
}
// 拖拽体
const SortableItem = sortableElement(({ value,sortIndex }) => {
return (
<ListItem>
<DragHandle />
<ChildCom>
<ComSortItem data={value} index={sortIndex} updateData={updateData} />
</ChildCom>
</ListItem>
);
});
// 拖拽后回调
const onSortEnd = ({ oldIndex, newIndex }) => {
const List = arrayMoveImmutable(dataSource, oldIndex, newIndex);
sortEnd(List);
};
return (
<>
<SortableContainer onSortEnd={onSortEnd} useDragHandle>
{dataSource.length > 0 &&
dataSource.map((value, index) => (
<SortableItem
key={`sortable-item-${index}`}
index={index}
value={value}
sortIndex={index}
/>
))}
</SortableContainer>
</>
);
}
export default Sortable;
2、调用sortable组件
import React from 'react'
import { Checkbox } from 'antd'
import Sortable from 'component/Sortable'
import AddForm from './add'
import styled from '@emotion/styled'
const ItemBox = styled.div`
display: flex;
justify-content: space-between;
.name{
width: 100%;
overflow: hidden; //超出的文本隐藏
text-overflow: ellipsis; //溢出用省略号显示
white-space: nowrap; //溢出不换行
}
`
const Opt = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
`
const RightBox = styled.div`
width: 250px;
border: 1px solid #ddd;
display: flex;
flex-direction: column;
border: 1px solid #d9d9d9;
border-radius: 2px;
.item-con {
padding: 10px;
}
`
// 自定义拖拽体
function AddForm(props) {
const { data, updateData, index } = props
const { attributeName, checked } = data
const changeChecked = (e) => {
const isChecked = e.target.checked
updateData({ ...data, checked: isChecked}, index)
}
return (
<ItemBox>
<div className='name'>{attributeName}</div><Opt>
<Checkbox onChange={changeChecked} checked={checked} ></Checkbox>
</Opt>
</ItemBox>
)
}
const Right = (props) => {
// dataSource 数据列表 setRightList拖拽后回调函数
const { dataSource, setRightList } = props
const updateSource = (val) => {
setRightList(val)
}
return (
<RightBox>
<div className='item-con' style={{ height: '400px', overflow: 'auto' }}>
<Sortable
className='sortable'
dataSource={dataSource}
ComSortItem={(p) => <AddForm {...p} />}
sortEnd={(val) => {
updateSource(val)
}}
/>
</div>
</RightBox>
)
}
export default Right
完工。
?
|