问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

react实现组件拖拽自定义模板(react-dnd),组件自定义大小功能(react-rnd...

发布网友 发布时间:2024-10-03 04:34

我来回答

1个回答

热心网友 时间:2024-10-21 10:36

前言:之前需要做一个关于拖拽实现自定义模板的功能一开始也是一脸懵逼的,后面通过查询一些资料和广大群友的帮助完成了该功能!该文章仅介绍功能所需内容不做过多的功能介绍,第一次记录,不喜勿喷!

正文:本文章只做必要的解释,大部分解释在代码中!一:react-dnd,官网地址:https://react-dnd.github.io/react-dnd/docs/tutorial1.1下载yarnaddreact-dndreact-dnd-html5-backendnpminstallreact-dndreact-dnd-html5-backend1.2引入index.jsximport{DndProvider}from'react-dnd';import{HTML5Backend}from'react-dnd-html5-backend';constreactDnd=()=>{return(<divclassName="AppBox"><DndProviderbackend={HTML5Backend}><Ground/></DndProvider></div>)}exportdefaultreactDnd;

DndProvider:组件的应用程序提供React-DnD功能。必须通过backendc参数将其注入后端,但是也可以将其注入window对象。(可以理解为:拖拽发生在DndProvider这个盒子里面)

1.3拖拽盒子Container.jsxconstContainer=()=>{const[dataType,setDataType]=useState()const[wh,setWh]=useState({leftWidth:0,rightWidth:0})useEffect(()=>{setTimeout(()=>{vardiv=document.getElementById("GroudBox_left");varw=Math.round(div.offsetWidth);varh=Math.round(div.offsetHeight);setWh({leftWidth:w,rightWidth:h})},500)},[])//拖拽组件数据letlist=[{title:'Dragmearound3',id:3,left:0,top:0,style:{width:"100px",height:"100px",background:"darkkhaki"}]constdata={setDataType,dataType,list,wh}return(<divclassName="GroudBox"id="GroudBox"><divclassName="GroudBox_left"id="GroudBox_left">//拖拽组件{list.map((item,index)=>{return(<Btnkey={index}item={item}{...data}/>)})}</div><divclassName="GroudBox_right"><DustBin{...data}/>//拖拽模板</div></div>)}exportdefaultContainer;

这个组件很简单,包含了一个左侧需要拖拽的组件右侧的一个拖拽进的模板

1.4被拖拽的组件Btn.jsx

useDrag:声明拖动源,用于将当前组件用作拖动源的钩子(drag这个组件的是用来拖拽的)

import{Button}from"antd";import{useDrag,useDrop}from"react-dnd";import{ItemTypes}from"../ItemTypes";constBtn=({item,setDataType})=>{const[{isDragging},drag]=useDrag(()=>({type:ItemTypes.BOX,//必填,并且必须是字符串,ES6符号。只有注册为相同类型的放置目标才会对此项目做出反应end:(monitor)=>{console.log("拖动的组件",item);setDataType(item)},//监听collect:(monitor)=>({//监听是否在动isDragging:monitor.isDragging(),getDropResult:monitor.getDropResult()})}))return(<Buttonref={drag}type="primary"style={{marginTop:"1rem"}}>组件{item.id}</Button>)}exportdefaultBtn;1.5ItemTypes.jsxexportconstItemTypes={BOX:'box',}

主要是绑定type的目标类型

1.6拖拽模板DustBin.jsx

useDrag:声明拖动范围,用于将拖动源的钩子拖入的范围(drop这个组件接受来拖拽来的组件)

import{useState,useEffect,useCallback}from'react'import{useDrop}from'react-dnd'import{ItemTypes}from'../ItemTypes.js';import{Rnd}from"react-rnd";letdata,boxconstDustBin=({dataType,list,wh})=>{const[boxes,setBoxes]=useState([{top:20,left:80,title:'Dragmearound',id:1},{top:180,left:20,title:'Dragmetoo',id:2},])//当前组件拖动constmoveBox=useCallback((id,left,top)=>{boxes.forEach(item=>{if(item.id===id){item.left=leftitem.top=top}})setBoxes([...boxes])},[boxes,setBoxes],)const[,drop]=useDrop(()=>({accept:ItemTypes.BOX,drop(item,monitor){console.log(item)//拖动的组件数据},}),[moveBox],)return(<divref={drop}className="template">//拖入的组件{boxes.map(item)=>{return(<div>{item.title}</div>)}}</div>)}exportdefaultDustBin;

drop(item,monitor):选填。当兼容项目放在目标上时调用。您可以返回undefined或纯对象。如果返回一个对象,它将成为放置结果,并且可用于其拖动源中的endDrag方法monitor.getDropResult()。主要的作用是获取拖动后获取当前组件最后的X,Y的值(monitor.getDifferenceFromInitialOffset())

后面发现react-dnd只能拖动组件在拖入模板盒子的时候无法获取到当前的数据,所以无法满足从左拖拽到右放入模板盒子,可能是没有仔细看官网的缘故,有其他办法的没有小伙伴可以留言,下面是我的解决方案

DustBin.jsx完整代码

import{useState,useEffect,useCallback}from'react'importupdatefrom'immutability-helper'import{useDrop}from'react-dnd'import{ItemTypes}from'../ItemTypes.js';letdata,boxconstDustBin=({dataType,list,wh})=>{const[boxes,setBoxes]=useState([])const[typeId,setTypeId]=useState()useEffect(()=>{console.log("拿到的组件",dataType);data=dataType},[dataType])useEffect(()=>{console.log("拿到的宽高",wh);box=wh},[wh])//当前组件拖动constmoveBox=useCallback((id,left,top)=>{boxes.forEach(item=>{if(item.id===id){item.left=leftitem.top=top}})setBoxes([...boxes])},[boxes,setBoxes],)//新组件拖入constnewMoveBox=useCallback((id,left,top)=>{list.forEach(item=>{if(item.id===id){item.left=leftitem.top=topboxes.push(item)}})setBoxes([...boxes])},[boxes,setBoxes],)const[,drop]=useDrop(()=>({accept:ItemTypes.BOX,drop(item,monitor){constdelta=monitor.getDifferenceFromInitialOffset()constnewdelta=monitor.getClientOffset()if(item.id){constleft=Math.round(item.left+delta.x)consttop=Math.round(item.top+delta.y)moveBox(item.id,left,top)}else{constleft=Math.round(delta.x-box.leftWidth)consttop=Math.round(newdelta.y)setTimeout(()=>{console.log(data);newMoveBox(data.id,left,top)},500)}returnundefined},}),[moveBox],)useEffect(()=>{console.log(boxes);},[boxes])constboxDataBtn=(id,x,y)=>{console.log(id,x,y);boxes.forEach(item=>{if(item.id===id){item.left=310;item.top=224;console.log(item);}})setBoxes([...boxes])}constfunctionBtn={boxDataBtn}return(<divref={drop}className="template">{boxes.map((key,index,)=>{const{id,left,top,style}=keyreturn(<div>222</div>)})}</div>)}exportdefaultDustBin;

简单说明一下,在Btn.jsx中的useDrag里面获取到被拖拽的组件(见Btn.jsx-14行)后再放入DustBin.jsx的boxes中这样就能准确的拿到当前拖拽的组件放入模板中了!

二:react-rnd地址:https://github.com/bokuweb/react-rnd

这是一个自定义组件的拖动,大小的一个插件

下载

npmi-Sreact-rnd

yarnaddreact-rnd

2.1使用import{Rnd}from"react-rnd";constDustBin=({dataType,list,wh})=>{return(<Rndkey={key.id+index}default={{x:left,y:top,width:200,height:200}}bounds="parent"//拖动范围/*parent限制节点的offsetParent内的移动(位置相对或绝对的最近节点)window,body,或选择器,如.fooClassName*/style={{position:'absolute',cursor:"pointer",left,top,...style}}onDragStop={(e,d)=>{console.log(d.x,d.y);console.log(id);}}lockAspectRatio={false}//盒子的尺寸列如(16/9)className="rndBox"onResizeStop={(e,direction,ref,delta,position)=>{//this.setState({//width:ref.style.width,//height:ref.style.height,//...position,//拉伸后的位置//});}}>2222</Rnd>)}exportdefaultDustBin;总结

这次的功能一共用了两个东西react-dnd+react-rnd,不是必要的东西就没有写备注如果没有满足要求的话请前往官网查看!

再次感谢群友推荐的插件感谢头上有煎饺鸽鸽!原文:https://juejin.cn/post/7098594714340818952
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
临沂比较有名的男装品牌 呼伦贝尔市悦动网络科技有限公司怎么样? 呼伦贝尔中汇实业有限公司怎么样? 呼伦贝尔油玉不绝电子商务有限公司怎么样? 如何避免wps卡顿? 属鼠的男人找对象是属什么,属鼠的人和什么属相合 96年鼠的姻缘在哪年 属相相合年份运势提升 2024属鼠找对象属什么最佳 黑客攻击网站能报案吗 黑客攻击报案有用吗 React Draggable 实现拖拽 - 最详细中文教程 - 卡拉云 云顶之弈10.14暗星秘刺星神狙怎么玩_10.14版本暗星秘刺星神狙阵容玩法... 云顶之弈10.14圣盾星守法怎么玩_10.14版本圣盾星守法阵容玩法攻略 云顶之弈10.14爆破机甲刺秘法阵容怎么玩_10.14爆破机甲刺秘法阵容推荐... Linux文件系统制作与裁剪 ...疼,有的时候疼到腿都抬不起来,照X光说骨骼没有事,可是只有一_百度知 ... ...坐,现在左脚膝盖右侧的骨头一按就痛。蹲下再起来也酸痛。要扶着东 ... 我的膝盖一按就疼跑步的时候也疼,就走路不疼。我有两个月没跑步,就前... 情人之间索要分手费合法的吗 什么是德育活动? 为什么用PS保存jpg图片那么大? 为什么ps导出的图片尺寸变大了? 为什么PS切片后导出的图片那么大? ...情人节,平安夜在中国都很流行。其实我对国外节日一定 梦见我抓住了一条银色的龙 ps内存很大怎么变小 女生把我拉黑了,我不知道她家和工作地址,估计生气啥的,应该没有... 披萨如何制作得饼底薄脆、馅料口感丰富? 撞完护栏直接就走算逃逸吗 脆底鲜虾披萨的制作方法有哪些? 为什么两个奇数相加得到的还是奇数呢? 从中山横栏镇高速入口到湖南涟源市政府有多远 因为奇数项之和为奇数,故此数列有奇数个奇数,这是什么意思,后面这句... 从广东中山横栏镇自驾回湖南益阳会经过虎门高铁站吗? 1+2+3+...+87的和是奇数还是偶数,为什么? 在PS里怎样将一张图片在不改变长和宽的前提下将内存变小 70个连续自然数相加和是奇数还是偶数?为什么? 怎样将100k的照片压缩到15~25k?急!!! 怎么用PS把照片兆数变成15K以内的 真正的自律是找到属于自己的规律和节奏,如何拥有自律,记住哪几点? 康王洗剂产品优势 康王和采乐哪个好 童熙萌悦教育平台可以么 Ipad2翻新机问题 序列号:dlxgpweadkph , 平板电脑mgpw2ch/a和平板电脑mgq32ch/a 有什么区别 ...插在电脑上耳机有声音,但话筒没声音是怎么回事?(电脑是 为什么头戴式耳机插到三星电脑上,耳机里没声音,还在外放啊,耳机没问题... 五一去平谷玩什么 2018平谷桃花节时间+门票 windows的桌面背景图片放在哪了? 如何快速做石榴汁