h5中给元素新增了draggable全局属性,定义了元素的可拖拽属性。在项目中,拖拽排序也是比较常见的需求。
截屏2021-12-16 下午4.17.26.png
上图view层的代码如下
const SelectArea = observer((props: { store: Store; }): React.ReactElement => {
const { categoryIconList, deleteWashIcon, emptyIconNum, onDrag } = props.store;
useLayoutEffect(() => {
onDrag();
}, []);
return (
<div
className={styles.selectArea}
id="selectArea"
>
<Alert
banner
className={styles.alert}
icon={(<InfoCircleOutlined/>)}
message="最多选择8个图标,支持长按拖动排序"
type="info"
/>
<Row style={{ alignItems: 'center' }}>
{
categoryIconList.map((item) => (
<EachIcon
deleteWashIcon={() => {
deleteWashIcon(item);
}}
key={item}
showDelete
url={item}
/>
))
}
{
emptyIconNum.map((item) => (
<AddIcon key={item}/>
))
}
<Col span={3}>
<Button type="primary">
保存
</Button>
</Col>
</Row>
</div>
);
});
在拖动上图的图标时可以交换图标的位置,具体的逻辑和代码实现如下,在组件挂载时将onDrag方法执行。
// 拖动排序事件绑定
public onDrag = () => {
const selectArea = document.getElementById('selectArea');
selectArea.addEventListener('dragstart', (e) => {
// @ts-ignore
const dragUrl = e.target.getAttribute('src');
this.dragIndex = this.categoryIconList.findIndex((item) => item === dragUrl);
});
// 将dragover的默认事件取消后才能触发drop事件
selectArea.addEventListener('dragover', (e) => {
e.preventDefault();
});
selectArea.addEventListener('drop', (e) => {
// @ts-ignore
if (e.target.nodeName !== 'IMG') {
return;
}
// @ts-ignore
const dragTargetUrl = e.target.getAttribute('src');
const targetInex = this.categoryIconList.findIndex((item) => item === dragTargetUrl);
if (this.dragIndex === targetInex) {
ret
}
this.categoryIconList = this.swap(this.categoryIconList, this.dragIndex, targetInex);
this.dragIndex = -1;
});
};
该段代码的逻辑如下,采用事件委托的方式给这些图标的父级元素selectArea绑定dragstart和drop方法,通过e.target来获取img的src值,从而获取数组的index值实现换序。设置了draggable属性的元素即可触发drag的一系列方法(图片和链接是默认自带draggable属性)。要注意的是为了触发元素的ondrop方法,要将元素的dragover默认事件取消掉。