前端原生js實(shí)現(xiàn)拖拽排課效果實(shí)例
1. 效果展示
如圖所示,頁面左側(cè)有一個(gè)包含不同課程(如語文、數(shù)學(xué)等)的列表,頁面右側(cè)是一個(gè)表格,表示一周內(nèi)每天的不同時(shí)間段。用戶可以通過拖拽左側(cè)的課程到右側(cè)的時(shí)間表中,來安排課程。

2. 效果分析
目標(biāo):鼠標(biāo)摁下左側(cè)某一科目,拖拽到右側(cè)某一位置放下,拖拽的課程就會(huì)嵌入到課表框當(dāng)中
2.1 關(guān)鍵點(diǎn)
(1) 拖拽與放置邏輯的實(shí)現(xiàn)
(2) HTML與CSS布局的設(shè)計(jì)
2.2 實(shí)現(xiàn)方法
(1) 將拖拽過程分為 開始拖拽、允許放置、放置三部分分析。
(2) 頁面主要由兩部分組成——左側(cè)是可拖動(dòng)的課程項(xiàng)列表,右側(cè)是一個(gè)表格,用于顯示每周的時(shí)間安排。每個(gè)課程項(xiàng)都設(shè)定了 draggable = "true" 屬性,使其可以被拖動(dòng)。表格中的 <td> 元素(不包括第一列)是可以放置課程的目標(biāo)區(qū)域。
(3) 通過 CSS 確保頁面居中顯示,并設(shè)置了 .box 容器的尺寸和邊框。.left 和 .right 分別代表課程項(xiàng)列表和時(shí)間表的位置和大小。
3. 代碼實(shí)現(xiàn)
接下來我會(huì)一步一步解說每段關(guān)鍵代碼的含義。
3.1 html部分
<div class="box">
<div class="left">
<div class="yu" draggable="true">語文</div>
<div class="shu" draggable="true">數(shù)學(xué)</div>
<div class="ying" draggable="true">英語</div>
<div class="wu" draggable="true">物理</div>
<div class="hua" draggable="true">化學(xué)</div>
<div class="sheng" draggable="true">生物</div>
</div>
<div class="right">
<table>
<tr>
<th>時(shí)間/星期</th>
<th>星期一</th>
<th>星期二</th>
<th>星期三</th>
<th>星期四</th>
<th>星期五</th>
</tr>
<tr>
<td>08:00-09:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>10:00-11:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>11:00-12:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>12:00-13:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>14:00-15:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>15:00-16:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
左側(cè)是課程列表, 該部分包含六個(gè) <div> 元素,每個(gè)元素代表一門課程(如語文、數(shù)學(xué)等),并賦予了 draggable = "true" 屬性,這意味著這些課程項(xiàng)可以被拖動(dòng)。
右側(cè)是時(shí)間表,提供了五個(gè)工作日(周一至周五)和六個(gè)上課時(shí)段的時(shí)間框架,使得用戶可以直觀地安排每周的課程。
3.2 css部分
.left {
width: 150px;
display: flex;
flex-direction: column;
justify-content: space-between;
gap: .7rem;
}
.left > div {
width: 100%;
height: 50px;
border: 1px solid black;
text-align: center;
line-height: 50px;
font-weight: bold;
letter-spacing: 4px;
cursor: move;
}
.yu { background: lawngreen; }
.shu { background: skyblue; }
.ying { background: mediumslateblue; }
.wu { background: aqua; }
.hua { background: violet; }
.sheng { background: navajowhite; }
.right {
width: 750px;
height: 400px;
overflow: auto;
}css部分沒什么好說的,按照自己的喜好隨意編寫即可。
3.3 js部分
const draggables = document.querySelectorAll('.left > div');
const droppables = document.querySelectorAll('.right td:not(:first-child)');獲取所有可拖動(dòng)的課程項(xiàng) 和 所有可放置課程的時(shí)間段單元格(不包括第一列)。
draggables.forEach(draggable => {
draggable.addEventListener('dragstart', e => {
e.dataTransfer.setData('text/plain', e.target.className);
e.dataTransfer.dropEffect = 'move';
});
});拖拽開始::當(dāng)用戶開始拖動(dòng)一個(gè)課程項(xiàng)時(shí),瀏覽器觸發(fā) dragstart 事件。在這個(gè)事件處理函數(shù)中,我們使用 setData 方法將被拖拽元素的類名作為數(shù)據(jù)存儲(chǔ)在 Datatransfer 對(duì)象中。同時(shí),設(shè)置drapEffect 屬性為 ‘move’,以表明這是一個(gè)移動(dòng)操作。
droppables.forEach(droppable => {
droppable.addEventListener('dragover', e => {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
});
});允許放置: 當(dāng)拖拽元素經(jīng)過目標(biāo)單元格時(shí),瀏覽器會(huì)觸發(fā) dragover 事件。默認(rèn)情況下,瀏覽器會(huì)阻止這個(gè)事件,所以我們需要調(diào)用 preventDefault() 來允許放置。同樣地,我們?cè)O(shè)置 dropEffect為 ‘move’,以便與 dragstart 中的設(shè)置相匹配。
droppable.addEventListener('drop', e => {
e.preventDefault();
const draggedItemClass = e.dataTransfer.getData('text/plain');
const draggedItem = document.querySelector(`.${draggedItemClass}`);
if (e.target.tagName === 'TD') {
e.target.textContent = draggedItem.textContent;
e.target.style.backgroundColor = window.getComputedStyle(draggedItem).backgroundColor;
}
});放置:當(dāng)用戶釋放鼠標(biāo)按鈕,拖拽元素被放置到目標(biāo)單元格時(shí),瀏覽器觸發(fā) drap 事件。在這個(gè)事件處理函數(shù)中,我們獲取之前存儲(chǔ)的數(shù)據(jù)(即課程項(xiàng)的類名),找到對(duì)應(yīng)的課程項(xiàng),并將其內(nèi)容和背景顏色復(fù)制到目標(biāo)單元格中。
3.4 完整代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拖拽實(shí)現(xiàn)排課</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.box {
width: 1000px;
height: 600px;
border: 1px solid red;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
box-sizing: border-box;
}
.left {
width: 150px;
display: flex;
flex-direction: column;
justify-content: space-between;
gap: .7rem;
}
.left > div {
width: 100%;
height: 50px;
border: 1px solid black;
text-align: center;
line-height: 50px;
font-weight: bold;
letter-spacing: 4px;
cursor: move;
}
.yu { background: lawngreen; }
.shu { background: skyblue; }
.ying { background: mediumslateblue; }
.wu { background: aqua; }
.hua { background: violet; }
.sheng { background: navajowhite; }
.right {
width: 750px;
height: 400px;
overflow: auto;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
width: 120px;
height: 50px;
border: 1px solid black;
text-align: center;
}
td {
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
<div class="left">
<div class="yu" draggable="true">語文</div>
<div class="shu" draggable="true">數(shù)學(xué)</div>
<div class="ying" draggable="true">英語</div>
<div class="wu" draggable="true">物理</div>
<div class="hua" draggable="true">化學(xué)</div>
<div class="sheng" draggable="true">生物</div>
</div>
<div class="right">
<table>
<tr>
<th>時(shí)間/星期</th>
<th>星期一</th>
<th>星期二</th>
<th>星期三</th>
<th>星期四</th>
<th>星期五</th>
</tr>
<tr>
<td>08:00-09:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>10:00-11:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>11:00-12:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>12:00-13:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>14:00-15:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>15:00-16:00</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
<script>
// 獲取所有可拖動(dòng)的課程項(xiàng)
const draggables = document.querySelectorAll('.left > div');
// 獲取所有可放置課程的時(shí)間段單元格(不包括第一列)
const droppables = document.querySelectorAll('.right td:not(:first-child)');
// 添加拖拽開始事件監(jiān)聽器
draggables.forEach(draggable => {
draggable.addEventListener('dragstart', e => {
e.dataTransfer.setData('text/plain', e.target.className);
e.dataTransfer.dropEffect = 'move';
});
});
// 添加拖拽進(jìn)入和放置事件監(jiān)聽器
droppables.forEach(droppable => {
droppable.addEventListener('dragover', e => {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
});
droppable.addEventListener('drop', e => {
e.preventDefault();
const draggedItemClass = e.dataTransfer.getData('text/plain');
const draggedItem = document.querySelector(`.${draggedItemClass}`);
if (e.target.tagName === 'TD') {
e.target.textContent = draggedItem.textContent;
e.target.style.backgroundColor = window.getComputedStyle(draggedItem).backgroundColor;
}
});
});
</script>
</body>
</html>4. 總結(jié)
到此這篇關(guān)于前端原生js實(shí)現(xiàn)拖拽排課效果的文章就介紹到這了,更多相關(guān)原生js拖拽排課效果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript的動(dòng)態(tài)增加類的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄狫avascript的動(dòng)態(tài)增加類的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-10-10
用函數(shù)式編程技術(shù)編寫優(yōu)美的 JavaScript_ibm
函數(shù)式編程語言在學(xué)術(shù)領(lǐng)域已經(jīng)存在相當(dāng)長(zhǎng)一段時(shí)間了,但是從歷史上看,它們沒有豐富的工具和庫(kù)可供使用。隨著 .NET 平臺(tái)上的 Haskell 的出現(xiàn),函數(shù)式編程變得更加流行。一些傳統(tǒng)的編程語言,例如 C++ 和 JavaScript,引入了由函數(shù)式編程提供的一些構(gòu)造和特性。在許多情況下,JavaScript 的重復(fù)代碼導(dǎo)致了一些拙劣的編碼。如果使用函數(shù)式編程,就可以避免這些問題。此外,可以利用函數(shù)式編程風(fēng)格編寫更加優(yōu)美的回調(diào)。2008-05-05
JavaScript中常見的七種繼承及實(shí)現(xiàn)
JS的繼承方式在我們面試的時(shí)候經(jīng)常會(huì)被問到,所以深入理解js繼承方式以及它們的優(yōu)缺點(diǎn)是非常有必要的。本文為大家整理了JavaScript中常見的七種繼承及實(shí)現(xiàn),需要的可以參考一下2023-03-03
微信小程序?qū)崿F(xiàn)的日期午別醫(yī)生排班表功能示例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)的日期午別醫(yī)生排班表功能,結(jié)合實(shí)例形式分析了微信小程序?qū)崿F(xiàn)基于日期時(shí)間、針對(duì)上午、下午、凌晨、夜間等時(shí)段的排班功能相關(guān)操作技巧,需要的朋友可以參考下2019-01-01
javasript實(shí)現(xiàn)密碼的隱藏與顯示
用戶輸入密碼時(shí)都是顯示的星號(hào)了,那么我們希望查看明文要怎么查看呢,下面我們只要使用一段簡(jiǎn)單的js就可以實(shí)現(xiàn)查看密碼框的明文了,有需要的小伙伴可以來參考下。2015-05-05
在小程序中集成redux/immutable/thunk第三方庫(kù)的方法
這篇文章主要介紹了在小程序中集成redux/immutable/thunk第三方庫(kù)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08
javascript實(shí)現(xiàn)上傳圖片并預(yù)覽的效果實(shí)現(xiàn)代碼
圖片上傳預(yù)覽,就是在使用文件選擇框選擇了文件之后就可以在頁面上看見圖片的效果,關(guān)于這個(gè)效果我一直認(rèn)為是無法做到的2011-04-04

