简介
- 能将任意列表转换为可拖动排序的 React 高阶组件,可将任何列表转换为动画,可访问和触摸友好的可排序列表 .
React 社区提供了许多的库来实现拖放的功能,例如 react-dnd, react-beautiful-dnd, react-drag-n-drop,等等。但是它们有一些共同的缺陷:
- 使用复杂,有时候需要做很多工作才能构建一个简单的拖放演示;
- 功能有限,例如无法实现多个拖放实例这样复杂的功能,
为了解决这些问题,react-sortable-hoc 应运而生。
React 官方推荐的封装高阶组件的方式是 HOC,我们需要借助它来实现一个具有拖放功能的高阶组件。
- HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
- HOC:
higher Order Component
,高阶组件。本质上是参数为组件,返回值为新组件的函数。
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import React, {Component} from 'react'; import {render} from 'react-dom'; import {SortableContainer, SortableElement} from 'react-sortable-hoc'; import arrayMove from 'array-move';
const SortableItem = SortableElement(({value}) => <li>{value}</li>);
const SortableList = SortableContainer(({items}) => { return ( <ul> {items.map((value, index) => ( <SortableItem key={`item-${index}`} index={index} value={value} /> ))} </ul> ); });
class SortableComponent extends Component { state = { items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'], }; onSortEnd = ({oldIndex, newIndex}) => { this.setState(({items}) => ({ items: arrayMove(items, oldIndex, newIndex), })); }; render() { return <SortableList items={this.state.items} onSortEnd={this.onSortEnd} />; } }
render(<SortableComponent />, document.getElementById('root'));
|
例子2
准备拖拽的元素
1 2 3 4 5 6 7 8 9 10 11 12
| import React, { useState } from 'react'; import React from 'react'; import PropTypes from 'prop-types';
const Gif = ({ gif }) => (<img src={gif} alt="gif" />)
Gif.propTypes = { gif: PropTypes.string.isRequired, };
export default Gif;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import React, { useState } from 'react'; import './App.css';
import Gif from './Gif';
const App = () => { const [gifs, setGifs] = useState([ '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', ]);
return ( <div className="App"> <h1>Drag those GIFs around</h1> <h2>Set 1</h2> {gifs.map((gif, i) => <Gif key={gif} gif={gif} />)} </div> ); }
export default App;
|
添加拖放功能
现在让我们对 Gif 组件添加拖拽功能。
首先,我们需要了解 react-sortable-hoc 的两个 HOC,以及 array-move 的 arrayMove
方法,以便于在拖动发生修改数组。
sortableContainer
是所有可排序元素的容器;
sortableElement
是每个可渲染元素的容器。
首先引入对应组件以及方法
1 2 3 4 5 6 7
| import { sortableContainer, sortableElement } from 'react-sortable-hoc'; import arrayMove from 'array-move';
const SortableGifsContainer = sortableContainer(({ children }) => <div className="gifs">{children}</div>);
const SortableGif = sortableElement(({ gif }) => <Gif key={gif} gif={gif} />);
|
然后用新创建的 SortableGif
替换原有的 Gif
组件,并在 SortableGifsContainer
中使用。
1 2 3 4 5 6 7 8 9 10
| <SortableGifsContainer axis="x" onSortEnd={onSortEnd}> {gifs.map((gif, i) => <SortableGif // don't forget to pass index prop with item index index={i} key={gif} gif={gif} /> )} </SortableGifsContainer>
|