组件文档 https://github.com/clauderic/react-sortable-hoc
在线demo https://clauderic.github.io/react-sortable-hoc/
npm install react-sortable-hoc --save
List拖拽
使用 distance prop设置触发排序之前要拖动的最小距离
- 例如设置10px的距离,distance={10}
- 这时直接点击就不会立即触发 SortableContainer上的点击事件
拖拽时可能会造成样式丢失,原因是你的样式可能存在父级
- 拖拽时 react-sorttable-hoc 会帮我们复制一份拖拽的dom节点,放到body下,
- 所以有父级样式就访问不到了。可以把样式直接写在body,注意class命名,别和其他冲突了

import React, { useEffect, useState } from 'react';import PropTypes from 'prop-types';import { List, Switch, InputNumber } from 'antd';import {SortableContainer, SortableElement,} from 'react-sortable-hoc';import { arrayMove } from '@utils/array';const itemStyle = { padding: '8px 15px', zIndex: 1000 };const SortableItem = SortableElement(({ value }) => {return (<List.Itemstyle={itemStyle}actions={[<InputNumbermin={0}max={100}size='small'defaultValue={value.sort}/>,<Switch checked={value.checked} />,]}>{value.title}</List.Item>);});const SortableList = SortableContainer(({ value }) => (<ListdataSource={value}renderItem={(item, index) =><SortableItem key={index} index={index} value={item} />}/>));SortList.propTypes = {value: PropTypes.array.isRequired,onChange: PropTypes.func.isRequired,};function SortList({ value, onChange }) {const [data, setList] = useState(value);useEffect(() => {setList(value);}, [value]);function onSortEnd({ oldIndex, newIndex }) {if (oldIndex === newIndex) return;const arr = arrayMove(data, oldIndex, newIndex);setList(arr);onChange(arr);};return (<SortableListvalue={data}onSortEnd={onSortEnd}distance={10}/>);}export default SortList;
九宫格拖拽
pressDelay设置低于300ms时,造成的问题:点击按钮click没有效果,解决:
- 在拖拽item项目里的class添加一个属性:
pointer-events: bounding-box即可点击 - distance={10} 设置拖拽的最小距离
- https://github.com/clauderic/react-sortable-hoc/issues/206
pointer-events 阻止hover、active、onclick等触发事件来
https://www.imooc.com/article/48022
http://clauderic.github.io/react-sortable-hoc/#/basic-configuration/grid?_k=vq2z4r
Card卡片拖拽
https://css-tricks.com/draggin-and-droppin-in-react/
https://segmentfault.com/a/1190000020151524
card/index.js

import React, { useState } from 'react';import styled from './index.module.less';import {arrayMove} from '@utils/func'import GifHoc from './GifHoc';const array = ['https://media.giphy.com/media/3ohhwoWSCtJzznXbuo/giphy.gif','https://media.giphy.com/media/l46CbZ7KWEhN1oci4/giphy.gif','https://media.giphy.com/media/3ohzgD1wRxpvpkDCSI/giphy.gif','https://media.giphy.com/media/xT1XGYy9NPhWRPp4pq/giphy.gif',]function Index() {const [gifs, setGifs] = useState(array);const [newGifs, setNewGifs] = useState(['https://media.giphy.com/media/xiOgHgY2ceKhm46cAj/giphy.gif','https://media.giphy.com/media/3oKIPuMqYfRsyJTWfu/giphy.gif','https://media.giphy.com/media/4ZgLPakqTajjVFOVqw/giphy.gif','https://media.giphy.com/media/3o7btXIelzs8nBnznG/giphy.gif',]);// 每次拖动或排序项目时触发function onSortEnd(item, e) {const { oldIndex, newIndex, collection } = item;console.log('onSortEnd', item, collection)if(collection === 'gifs') {return setGifs(arrayMove(gifs, oldIndex, newIndex));}setNewGifs(arrayMove(newGifs, oldIndex, newIndex));}return (<div className={styled.card}><h1 className={styled.h1}>Drag those GIFs around</h1><h2 className={styled.h2}>Set 1</h2><GifHocdataSource={gifs}collection="gifs"onSortEnd={onSortEnd}/><h2 className={styled.h2}>Set 2</h2><GifHocdataSource={newGifs}collection="newGifs"onSortEnd={onSortEnd}/></div>);}export default Index;
index.module.less
.card {background: #1a1919;color: #fff;min-height: 100vh;padding: 25px;text-align: center;.h1 {font-size: 52px;margin: 0;}.h2 {color: #f6c945;text-transform: uppercase;}.img {cursor: grab;height: 180px;width: 240px;}}
SortableContainer
import React from 'react';import PropTypes from 'prop-types';import { sortableContainer, sortableElement } from 'react-sortable-hoc';import styled from './index.module.less';import Gif from './Gif'// sortableContainer 所有可排序元素的容器const SortableGifsContainer = sortableContainer(({ children }) => <div className="gifs">{children}</div>);// sortableElement 每个拖拽元素的容器const SortableGif = sortableElement(({ gif, index }) =><Gif gif={gif} key={index} />);GifHoc.propTypes = {dataSource: PropTypes.array.isRequired,};function GifHoc({ dataSource, collection, onSortEnd }) {return (<SortableGifsContaineraxis="x" // x 轴拖拽onSortEnd={onSortEnd}>{dataSource.map((gif, i) =><SortableGif// don't forget to pass index prop with item indexindex={i}key={gif}gif={gif}collection={collection} // 属于哪个集合/>)}</SortableGifsContainer>);}export default GifHoc;
SortableItem
import React from 'react';import {string} from 'prop-types';import styled from './index.module.less';Gif.propTypes = {gif: string.isRequired,};function Gif({ gif }) {return (<img src={gif} alt="gif" className={styled.img}/>);}export default Gif;
