js拖拽事件实现简单选课功能

html

css 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html, body {
            width: 100%;
            height: 100%;
            min-width: 1100px;
            background-color: rgb(87, 202, 11);
        }
        .content {
            border-radius: 5px;
            color: #fff;
            font-weight: bolder;
            display: flex;
            align-items: center;
            justify-content: center;
            height: 100%;
            padding: 30px 50px;
        }
        .list {
            width: 130px;
            flex: none;
            background: rgb(212, 195, 109);
            border-radius: 10px;
            margin-right: 20px;
            padding: 10px 0;
        }
        .item {
            background-color: cornflowerblue;
            width: 80px;
            height: 45px;
            line-height: 45px;
            color: #fff;
            font-size: 18px;
            font-weight: bolder;
            border-radius: 10px;
            text-align: center;
            cursor: pointer;
            margin: 10px auto;
        }
        .courses-box {
            display: flex;
            align-items: center;
            justify-content: center;
            background-color: antiquewhite;
            border-radius: 10px;
            flex: none;
            width: 900px;
            height: 600px;
            box-sizing: border-box;
            padding: 30px;
        }
        .time-box {
            width: 30px;
            flex: none;
            margin-right: 30px;
            padding-top: 30px;
        }
        .time {
            width: 30px;
            height: 200px;
            background-color: rgb(10, 164, 112);
            border-radius: 10px;
            margin-top: 15px;
            /* 文字排列方向 */
            writing-mode: vertical-lr;
            text-align: center;
            letter-spacing: 10px;
            padding-left: 3px;
        }
        .day-box {
            flex: 1;
            height: 100%;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            border-radius: 10px;
        }
        .day {
            width: 100%;
            flex: none;
            display: flex;
            align-items: center;
            justify-content: space-around;
        }
        .day span {
            width: 80px;
            height: 35px;
            line-height: 35px;
            margin-bottom: 10px;
            background-color: rgb(10, 164, 112);
            border-radius: 5px;
            text-align: center;
        }
        .courses {
            flex: 1;
            width: 100%;
            background-color: rgb(10, 164, 112);
            border-radius: 10px;
            display: flex;
            align-items: center;
            justify-content: space-around;
            padding: 10px;
        }
        .course-box {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: space-around;
        }
        .course {
            width: 90px;
            height: 50px;
            background-color: beige;
            margin: 5px 0;
            border-radius: 5px;
            display: flex;
            align-items: center;
        }
        .course:nth-child(4) {
            margin-bottom: 15px;
        }
        .drag-over {
            background-color: rgb(159, 69, 69);
        }
    </style>
</head>
<body>
    <div class="content">
        <div class="list" data-allowed="move">
        	<!-- draggable为true元素才能拖拽 -->
            <div class="item" draggable="true" data-effect="copy">语文</div>
            <div class="item" draggable="true" data-effect="copy">数学</div>
            <div class="item" draggable="true" data-effect="copy">英语</div>
            <div class="item" draggable="true" data-effect="copy">科学</div>
            <div class="item" draggable="true" data-effect="copy">体育</div>
            <div class="item" draggable="true" data-effect="copy">地理</div>
            <div class="item" draggable="true" data-effect="copy">历史</div>
            <div class="item" draggable="true" data-effect="copy">物理</div>
        </div>
        <div class="courses-box">
            <div class="time-box">
                <div class="time">上午</div>
                <div class="time">下午</div>
            </div>
            <div class="day-box">
                <div class="day">
                    <span>星期一</span>
                    <span>星期二</span>
                    <span>星期三</span>
                    <span>星期四</span>
                    <span>星期五</span>
                    <span>星期六</span>
                    <span>星期日</span>
                </div>
                <div class="courses"></div>
            </div>
        </div>
    </div>
    <script src="./drag.js"></script>
</body>
</html>

js

css 复制代码
const content = document.querySelector('.content');
const coursesDom = document.querySelector('.courses');
const courses = new Array(7).fill({
    morning: new Array(4).fill(''),
    afternoon: new Array(4).fill(''),
})

const renderCourses = () => {
    courses.forEach((dayCourse) => {
        const { morning, afternoon } = dayCourse;
        const div = document.createElement('div');
        div.classList.add('course-box');
        [...morning, ...afternoon].forEach((course) => {
            const span = document.createElement('span');
            span.textContent = course;
            span.classList.add('course');
            span.dataset.allowed = 'copy';
            div.appendChild(span);
        });
        coursesDom.appendChild(div);
    });
}

renderCourses();

const clearStyle = () => {
    const doms = document.querySelectorAll('.drag-over');
    doms.forEach((dom) => {
        dom.classList.remove('drag-over');
    });
}

// 当前在拖拽的元素变量
let source = null;
content.ondragstart = (e) => {
    // e.target为当前拖拽的元素
    console.log('srart', e.target);
    // 改变鼠标样式为copy样式,为一个加号
    e.dataTransfer.effectAllowed = e.target.dataset.effect;  // 取值:move、copy等
    source = e.target;
};

content.ondragover = function(e) {
    e.preventDefault();
    // e.target为当前停留的元素,不停触发
    console.log('over', e.target);
};

const findParentNode = (node) => {
    while(node) {
        if (node.dataset && node.dataset.allowed) {
            return node;
        }
        node = node.parentNode;
    }
}

content.ondragenter = (e) => {
    e.preventDefault();
    // e.target为当前进入的元素
    console.log('enter', e.target);
    clearStyle();
    const node = findParentNode(e.target);
    if (!node) {
        return;
    }
    if (source.dataset.effect === node.dataset.allowed) {
        e.target.classList.add('drag-over');
    }
};

content.ondragleave = (e) => {
    // e.target为当前离开的元素
    console.log('leave', e.target);
};

content.ondrop = (e) => {
    clearStyle();
    // e.target松开鼠标时所在的元素,这个方法能被触发,要确保ondragover中 e.preventDefault();因为元素默认是不允许其他元素拖到上面的
    console.log('drop', e.target);
    if (source.dataset.effect === e.target.dataset.allowed) {
        if (source.dataset.effect === 'copy') {
            e.target.innerHTML = '';
            const dom  = source.cloneNode(true);
            dom.dataset.effect = 'move';
            e.target.appendChild(dom);
        } else {
            // 清空所有子元素
            source.remove();
        }
    }
};

效果图

相关推荐
清秋32 分钟前
全网最全 ECMAScript 攻略( 更新至 ES2026)
前端·javascript·编程语言
Hilaku1 小时前
为什么 AI 写前端时,总是优先选择 React,而不是 Vue?
前端·javascript·程序员
不简说4 小时前
拖拽DIY表格插件来了!sv-print 七月更新:这次真的能自己拼表格了
前端·javascript·前端框架
weixin_471383034 小时前
Next.js - 04 - 深入理解next.js渲染原理
前端·javascript·next.js
ssshooter4 小时前
小程序分包页面报 "has not been registered yet" 的隐蔽根因:一个动态 import 拖垮整个分包
前端·javascript·微信小程序
鹏多多4 小时前
Web浏览器后台离线通知方案实现以及兼容指南
前端·javascript·vue.js
yangmu32034 小时前
Vue3 响应式系统深度解析:从 Proxy 到依赖追踪
前端·javascript·vue.js
Asize5 小时前
Node path 与 fs 模块:从回调地狱到 async await 的异步进化
javascript·node.js
大家的林语冰7 小时前
😭 Electron 麻了,Deno 直接支持二进制应用,无需第三方桌面应用框架!
前端·javascript·node.js
Ivanqhz7 小时前
NFM(神经因子分解机)
开发语言·javascript·人工智能·算法·蓝桥杯