使用react 实现拖拽功能
<h3>一、关于拖动</h3><p style="margin-left: 30px">图片默认可以拖动,其他元素的拖动效果同图片。正常的 div 是不能被拖动的,鼠标点击选择后移动没有效果,需要加 <span style="text-decoration: underline">draggable="true" </span>使得元素可以被拖动。</p>
<h3>二、拖拽相关的几个事件</h3>
<p style="margin-left: 30px">被拖拽元素的事件:ondragstart,ondragend </p>
<p style="margin-left: 30px">放置元素的事件:ondragenter、ondragover、ondragleave、ondrop </p>
<p style="margin-left: 30px">顾名思义,不需要解释。</p>
<p style="margin-left: 30px">需要注意是 ondragover 的默认事件 Reset the current drag operation to "none". 所以想让一个元素可放置,需要重写 ondragover </p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre>element.ondragover = event =><span style="color: rgba(0, 0, 0, 1)"> {
event.preventDefault();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
}</pre>
</div>
<p style="margin-left: 30px">当一个元素是可放置的,拖拽经过时鼠标会变成加号(cursor: copy;)<img src="https://img2020.cnblogs.com/blog/1895520/202011/1895520-20201111110222481-607359219.png" alt="" width="14" height="13" loading="lazy"></p>
<p style="margin-left: 30px"> 有一个对象 dataTransfer 可以用来存储拖拽数据。</p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre>dragEle.ondragstart = e => e.dataTransfer.setData('item', e.target.id);</pre>
</div>
<p style="margin-left: 30px">拖拽开始时触发,把被拖拽元素的 id 存入 <span class="cnblogs_code">e.dataTransfer </span></p>
<p style="margin-left: 30px">然后在 ondrop 的时候 可以获取到这个值 (ondragenter、ondragover、ondragleave 获取不到...)</p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre>putEle.ondrop = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e) {
let id </span>= e.dataTransfer.getData('item'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
}</pre>
</div>
<h3> 三、react中使用代码演示 [点击查看演示]</h3>
<p style="margin-left: 30px"> </p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<style><span style="color: rgba(0, 0, 0, 1)">
.item {
border: 1px solid #1da921;
width: 180px;
border</span>-<span style="color: rgba(0, 0, 0, 1)">radius: 5px;
box</span>-shadow: 0 0 5px 0<span style="color: rgba(0, 0, 0, 1)"> #b3b3b3;
margin: 5px auto;
background: #fff;
}
.item.active {
border</span>-<span style="color: rgba(0, 0, 0, 1)">style: dashed;
}
.item</span>-<span style="color: rgba(0, 0, 0, 1)">header {
font</span>-<span style="color: rgba(0, 0, 0, 1)">size: 12px;
color: #9e9e9e;
padding: 3px 5px;
}
.item</span>-<span style="color: rgba(0, 0, 0, 1)">main {
padding: 5px;
font</span>-<span style="color: rgba(0, 0, 0, 1)">size: 14px;
color: #</span>424242<span style="color: rgba(0, 0, 0, 1)">;
height: 36px;
overflow: hidden;
text</span>-<span style="color: rgba(0, 0, 0, 1)">overflow: ellipsis;
display: </span>-webkit-<span style="color: rgba(0, 0, 0, 1)">box;
</span>-webkit-box-<span style="color: rgba(0, 0, 0, 1)">orient: vertical;
</span>-webkit-line-clamp: 2<span style="color: rgba(0, 0, 0, 1)">;
}
.item</span>-header-<span style="color: rgba(0, 0, 0, 1)">point {
background: #ccc;
</span><span style="color: rgba(0, 0, 255, 1)">float</span><span style="color: rgba(0, 0, 0, 1)">: right;
padding: </span>0<span style="color: rgba(0, 0, 0, 1)"> 4px;
min</span>-<span style="color: rgba(0, 0, 0, 1)">width: 10px;
text</span>-<span style="color: rgba(0, 0, 0, 1)">align: center;
color: #fff;
border</span>-radius: 50%<span style="color: rgba(0, 0, 0, 1)">;
}
.col {
border: 1px solid #d2d2d2;
flex</span>-grow: 1<span style="color: rgba(0, 0, 0, 1)">;
width: 180px;
height: </span>100%<span style="color: rgba(0, 0, 0, 1)">;
margin: </span>0<span style="color: rgba(0, 0, 0, 1)"> 2px;
background: #eee;
flex</span>-grow: 1<span style="color: rgba(0, 0, 0, 1)">;
display: flex;
flex</span>-<span style="color: rgba(0, 0, 0, 1)">direction: column;
}
.col</span>-<span style="color: rgba(0, 0, 0, 1)">header {
height: 40px;
line</span>-<span style="color: rgba(0, 0, 0, 1)">height: 40px;
background: #1DA921;
color: #fff;
text</span>-<span style="color: rgba(0, 0, 0, 1)">align: center;
}
.col</span>-<span style="color: rgba(0, 0, 0, 1)">main {
overflow: auto;
flex</span>-grow: 1<span style="color: rgba(0, 0, 0, 1)">;
}
.col</span>-<span style="color: rgba(0, 0, 0, 1)">main.active {
background: #00ad23;
opacity: </span>0.1<span style="color: rgba(0, 0, 0, 1)">;
}
.task</span>-<span style="color: rgba(0, 0, 0, 1)">wrapper {
display: flex;
height: 400px;
width: 700px;
}
</span></style>
</head>
<body>
<div id="app"></div>
<script type="text/babel"><span style="color: rgba(0, 0, 0, 1)">
const STATUS_TODO </span>= 'STATUS_TODO'<span style="color: rgba(0, 0, 0, 1)">;
const STATUS_DOING </span>= 'STATUS_DOING'<span style="color: rgba(0, 0, 0, 1)">;
const STATUS_DONE </span>= 'STATUS_DONE'<span style="color: rgba(0, 0, 0, 1)">;
const STATUS_CODE </span>=<span style="color: rgba(0, 0, 0, 1)"> {
STATUS_TODO: </span>'待处理'<span style="color: rgba(0, 0, 0, 1)">,
STATUS_DOING: </span>'进行中'<span style="color: rgba(0, 0, 0, 1)">,
STATUS_DONE: </span>'已完成'<span style="color: rgba(0, 0, 0, 1)">
}
let tasks </span>=<span style="color: rgba(0, 0, 0, 1)"> [{
id: </span>0<span style="color: rgba(0, 0, 0, 1)">,
status: STATUS_TODO,
title: </span>'每周七天阅读五次,每次阅读完要做100字的读书笔记'<span style="color: rgba(0, 0, 0, 1)">,
username: </span>'小夏'<span style="color: rgba(0, 0, 0, 1)">,
point: </span>10<span style="color: rgba(0, 0, 0, 1)">
}, {
id: </span>1<span style="color: rgba(0, 0, 0, 1)">,
status: STATUS_TODO,
title: </span>'每周七天健身4次,每次健身时间需要大于20分钟'<span style="color: rgba(0, 0, 0, 1)">,
username: </span>'橘子🍊'<span style="color: rgba(0, 0, 0, 1)">,
point: </span>5<span style="color: rgba(0, 0, 0, 1)">
}, {
id: </span>2<span style="color: rgba(0, 0, 0, 1)">,
status: STATUS_TODO,
title: </span>'单词*100'<span style="color: rgba(0, 0, 0, 1)">,
username: </span>'┑( ̄Д  ̄)┍'<span style="color: rgba(0, 0, 0, 1)">,
point: </span>2<span style="color: rgba(0, 0, 0, 1)">
}, {
id: </span>3<span style="color: rgba(0, 0, 0, 1)">,
status: STATUS_TODO,
title: </span>'单词*150'<span style="color: rgba(0, 0, 0, 1)">,
username: </span>'┑( ̄Д  ̄)┍'<span style="color: rgba(0, 0, 0, 1)">,
point: </span>2<span style="color: rgba(0, 0, 0, 1)">
}, {
id: </span>4<span style="color: rgba(0, 0, 0, 1)">,
status: STATUS_TODO,
title: </span>'单词*200'<span style="color: rgba(0, 0, 0, 1)">,
username: </span>'┑( ̄Д  ̄)┍'<span style="color: rgba(0, 0, 0, 1)">,
point: </span>2<span style="color: rgba(0, 0, 0, 1)">
}, {
id: </span>5<span style="color: rgba(0, 0, 0, 1)">,
status: STATUS_TODO,
title: </span>'单词*250'<span style="color: rgba(0, 0, 0, 1)">,
username: </span>'┑( ̄Д  ̄)┍'<span style="color: rgba(0, 0, 0, 1)">,
point: </span>2<span style="color: rgba(0, 0, 0, 1)">
}]
class TaskItem extends React.Component {
handleDragStart </span>= (e) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.props.onDragStart(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.props.id);
}
render() {
let { id, title, point, username, active, onDragEnd } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.props;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
</span><<span style="color: rgba(0, 0, 0, 1)">div
onDragStart</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.handleDragStart}
onDragEnd</span>=<span style="color: rgba(0, 0, 0, 1)">{onDragEnd}
id</span>={`item-<span style="color: rgba(0, 0, 0, 1)">${id}`}
className</span>={'item' + (active ? ' active' : ''<span style="color: rgba(0, 0, 0, 1)">)}
draggable</span>="true"
>
<header className="item-header">
<span className="item-header-username">{username}</span>
<span className="item-header-point">{point}</span>
</header>
<main className="item-main">{title}</main>
</div>
<span style="color: rgba(0, 0, 0, 1)"> );
}
}
class TaskCol extends React.Component {
state </span>=<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">in</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
handleDragEnter </span>= (e) =><span style="color: rgba(0, 0, 0, 1)"> {
e.preventDefault();
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.props.canDragIn) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
</span><span style="color: rgba(0, 0, 255, 1)">in</span>: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
})
}
}
handleDragLeave </span>= (e) =><span style="color: rgba(0, 0, 0, 1)"> {
e.preventDefault();
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.props.canDragIn) {
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
</span><span style="color: rgba(0, 0, 255, 1)">in</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
})
}
}
handleDrop </span>= (e) =><span style="color: rgba(0, 0, 0, 1)"> {
e.preventDefault();
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.props.dragTo(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.props.status);
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
</span><span style="color: rgba(0, 0, 255, 1)">in</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
})
}
render() {
let { status, children } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.props;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
</span><<span style="color: rgba(0, 0, 0, 1)">div
id</span>={`col-<span style="color: rgba(0, 0, 0, 1)">${status}`}
className</span>={'col'<span style="color: rgba(0, 0, 0, 1)">}
onDragEnter</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.handleDragEnter}
onDragLeave</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.handleDragLeave}
onDragOver</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.handleDragEnter}
onDrop</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.handleDrop}
draggable</span>="true"
>
<header className="col-header"><span style="color: rgba(0, 0, 0, 1)">
{STATUS_CODE}
</span></header>
<main className={'col-main' + (<span style="color: rgba(0, 0, 255, 1)">this</span>.state.<span style="color: rgba(0, 0, 255, 1)">in</span> ? ' active' : '')}><span style="color: rgba(0, 0, 0, 1)">
{children}
</span></main>
</div>
<span style="color: rgba(0, 0, 0, 1)"> );
}
}
class App extends React.Component {
state </span>=<span style="color: rgba(0, 0, 0, 1)"> {
tasks: tasks,
activeId: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 传入被拖拽任务项的 id
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
onDragStart </span>= (id) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
activeId: id
})
}
dragTo </span>= (status) =><span style="color: rgba(0, 0, 0, 1)"> {
let { tasks,activeId} </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state;
let task </span>=<span style="color: rgba(0, 0, 0, 1)"> tasks;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (task.status !==<span style="color: rgba(0, 0, 0, 1)"> status) {
task.status </span>=<span style="color: rgba(0, 0, 0, 1)"> status;
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
tasks: tasks
})
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.cancelSelect();
}
cancelSelect </span>= () =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
activeId: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">
})
}
render() {
let { tasks, activeId } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state;
let { onDragStart, onDragEnd, cancelSelect } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
</span><div className="task-wrapper"><span style="color: rgba(0, 0, 0, 1)">
{
Object.keys(STATUS_CODE).map(status </span>=>
<<span style="color: rgba(0, 0, 0, 1)">TaskCol
status</span>=<span style="color: rgba(0, 0, 0, 1)">{status}
key</span>=<span style="color: rgba(0, 0, 0, 1)">{status}
dragTo</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.dragTo}
canDragIn</span>={activeId != <span style="color: rgba(0, 0, 255, 1)">null</span> && tasks.status !== status}><span style="color: rgba(0, 0, 0, 1)">
{ tasks.filter(t </span>=> t.status === status).map(t =>
<<span style="color: rgba(0, 0, 0, 1)">TaskItem
key</span>=<span style="color: rgba(0, 0, 0, 1)">{t.id}
active</span>={t.id ===<span style="color: rgba(0, 0, 0, 1)"> activeId}
id</span>=<span style="color: rgba(0, 0, 0, 1)">{t.id}
title</span>=<span style="color: rgba(0, 0, 0, 1)">{t.title}
point</span>=<span style="color: rgba(0, 0, 0, 1)">{t.point}
username</span>=<span style="color: rgba(0, 0, 0, 1)">{t.username}
onDragStart</span>=<span style="color: rgba(0, 0, 0, 1)">{onDragStart}
onDragEnd</span>=<span style="color: rgba(0, 0, 0, 1)">{cancelSelect}
</span>/>)
<span style="color: rgba(0, 0, 0, 1)"> }
</span></TaskCol>
<span style="color: rgba(0, 0, 0, 1)"> )
}
</span></div>
<span style="color: rgba(0, 0, 0, 1)"> )
}
}
ReactDOM.render(
</span><App />,
document.getElementById('app'<span style="color: rgba(0, 0, 0, 1)">)
);
</span></script>
</body>
</html></pre>
</div>
<h3>四、效果</h3>
<p style="margin-left: 30px"><img src="https://img2020.cnblogs.com/blog/1895520/202011/1895520-20201111111350101-388729124.png" alt="" loading="lazy"></p>
<h3>四、演示地址:</h3>
<p> 查看演示</p>
<p> </p>
<h3>五、原文来源</h3>
<p> 【我不吃饼干呀】 的博客 文章</p><br><br>
来源:https://www.cnblogs.com/art-poet/p/13957728.html
頁:
[1]