实现方法:1、利用“import{dndprovider}from 'react-dnd'”定义一个可拖拽的范围;2、利用“import{usedrag}from 'react-dnd'”将dragsource包裹住组件,使其可以拖动即可。
本教程操作环境:windows10系统、react17.0.1版、dell g3电脑。
react-dnd怎么实现拖拽react dnd是react和redux核心作者 dan abramov创造的一组react 高阶组件,可以在保持组件分离的前提下帮助构建复杂的拖放接口。
react dnd 的需求
默认使用 html5 拖放api,但支持
不直接操作 dom
dom 和拖放的源和目标解耦
融入html5拖放中窃取类型匹配和数据传递的想法
react dnd 的特点
专注拖拽,不提供现成组件
react dnd提供了一组强大的原语,但它不包含任何现成组件,而是采用包裹使用者的组件并注入 props 的方式。 它比jquery ui等更底层,专注于使拖放交互正确,而把视觉方面的效果例如坐标限制交给使用者处理。这其实是一种关注点分离的原则,例如react dnd不打算提供可排序组件,但是使用者可以基于它快速开发任何需要的自定义的可排序组件。
单向数据流
类似于 react 一样采取声明式渲染,并且像 redux 一样采用单向数据流架构,实际上内部使用了 redux
隐藏了平台底层api的问题
html5拖放api充满了陷阱和浏览器的不一致。 react dnd为您内部处理它们,因此使用者可以专注于开发应用程序而不是解决浏览器问题。
可扩展可测试
react dnd默认提供了html5拖放api封装,但它也允许您提供自定义的“后端(backend)”。您可以根据触摸事件,鼠标事件或其他内容创建自定义dnd后端。例如,内置的模拟后端允许您测试node环境中组件的拖放交互。
为未来做好了准备
react dnd不会导出mixins,并且对任何组件同样有效,无论它们是使用es6类,createreactclass还是其他react框架创建的。而且api支持了es7 装饰器。
示例如下:
1.1.使用dndprovider定义一个可以拖拽的范围
/* * @author: muge * @date: 2021-12-04 16:59:25 * @lasteditors: please set lasteditors * @lastedittime: 2021-12-08 14:24:47 */import react, { usestate } from 'react';import { dndprovider } from 'react-dnd';import { html5backend } from 'react-dnd-html5-backend';import sourcebox from './sourcebox';import targetbox from './targetbox';import treebox from './treebox';const item: any[] = [ { id: 1, name: 'muge', }, { id: 2, name: 'muxi', }, { id: 3, name: 'mugege', },];const container = () => { // 当前拖拽项 const [currentlist, setcurrentlist] = usestate<any>({}); return ( // 类似redux数据传输 需要在最外层包裹对象 <dndprovider backend={html5backend}> <h1>拖拽源组件 列表-----树</h1> <div style={{ display: 'flex' }}> <div> {/* 列表拖拽源 */} {item.map((itemz: any, index: number) => ( <sourcebox setcurrentlist={setcurrentlist} item={itemz} key={index} /> ))} </div> {/* 注意,不要树组件整体直接设置拖拽,抽成一个组件来遍历每一项 =》自定义渲染*/} {/* 树形拖拽源 */} <treebox /> </div> <h1>拖拽放置目标</h1> {/* 拖拽最终放置组件 */} <targetbox currentlist={currentlist} /> </dndprovider> );};export default container;
2.使用 dragsource 包裹住组件,使其可以进行拖动
/* * @author: muge * @date: 2021-12-07 14:26:08 * @lasteditors: please set lasteditors * @lastedittime: 2021-12-08 14:18:52 */import { usedrag } from 'react-dnd';const itemtypes = { box: 'box',};const style = { border: '1px dashed gray', backgroundcolor: 'white', padding: '0.5rem 1rem', marginright: '1rem', marginbottom: '1rem', cursor: 'move',};const sourcebox = ({ item, setcurrentlist }: any) => { const [{ opacity }, drag] = usedrag( () => ({ type: itemtypes.box, collect: (monitor) => ({ opacity: monitor.isdragging() ? 0.4 : 1, }), item: () => item, //返回当前列表项数据 candrag: (monitor) => { //是否取消拖拽 console.log(monitor, 'monitor131'); return true; }, // end(currentitem, monitor) { // monitor.getdropresult(); //获取拖拽对象所处容器的数据 // monitor.diddrop(); // 当前容器能否放置拖拽对象 拖动停止时触发 monitor.diddrop() && setcurrentlist(currentitem); //在容器点松开 才赋值 }, }), [], ); return ( <div ref={drag} style={{ ...style, opacity }}> {item.id}------{item.name} </div> );};export default sourcebox;
3.使用 droptarget 包裹住组件,使其对拖动,悬停或 dropped 的兼容项目做出反应。
/* * @author: muge * @date: 2021-12-07 14:26:08 * @lasteditors: please set lasteditors * @lastedittime: 2021-12-08 14:33:08 */import react from 'react';import { usedrop } from 'react-dnd';const itemtypes = { box: 'box',};const style: any = { border: '1px solid gray', height: '15rem', width: '15rem', padding: '2rem', textalign: 'center',};const targetbox = ({ currentlist }: any) => { const [{ isactive, isover, candrop }, drop] = usedrop(() => ({ accept: itemtypes.box, collect: (monitor) => ({ isactive: monitor.candrop() && monitor.isover(), isover: monitor.isover(), candrop: monitor.candrop(), }), // hover: (item, monitor) => { // console.log(item, 'item'); // console.log(monitor, 'monitor'); // }, })); // console.log(isover, 'isover'); // console.log(candrop, 'candrop'); return ( <div ref={drop} style={style}> {isactive ? 'release to drop' : 'drag item here'} <div style={{ backgroundcolor: 'pink', height: 30, display: 'flex', alignitems: 'center', justifycontent: 'center', fontsize: 17, fontweight: 600, width: '100%', }} > {json.stringify(currentlist) !== '{}' ? json.stringify(currentlist) : '当前item'} </div> </div> );};export default targetbox;
到此列表拖拽即可完成
推荐学习:《react视频教程》
以上就是react-dnd怎么实现拖拽的详细内容。