Vue『卡片拖拽式课程表』

news2024/9/23 9:33:44

Vue『卡片拖拽式课程表』

概述

在本篇技术博客中,我们将介绍一个使用Vue实现的『卡片拖拽式课程表』。这个课程表允许用户通过拖拽课程卡片来安排不同的课程在时间表上的位置。我们将逐步讲解代码实现,包括课程表的布局、拖拽功能的实现,以及如何动态显示课程信息。让我们一起开始吧!

项目概览

在我们的Vue『卡片拖拽式课程表』中,我们将有两个主要组件:CoursePanelvCoursePanel。其中CoursePanel组件表示每门课程的卡片,用于拖拽到时间表上;vCoursePanel则是时间表上的单元格,它可以接收被拖拽的课程卡片。

项目结构

我们的项目文件结构如下所示:- src/
  - components/
    - CoursePanel.vue
    - vCoursePanel.vue
  - views/
    - CourseSchedule.vue

CoursePanel.vuevCoursePanel.vue分别对应上述的两个主要组件,而CourseSchedule.vue则是我们主要的视图组件,包含了课程表的布局和逻辑。

CoursePanel组件

让我们先来看看CoursePanel.vue组件的代码:

<template>
  <div
    class="course-panel"
    draggable="true"
    @dragstart="handleDragStart"
    @dragend="handleDragEnd"
    :data-key="courseKey"
  >
    <h1>{{ courseName }}</h1>
    <span class="remove-btn">x</span>
  </div>
</template>

<script setup>
const props = defineProps({
  courseName: {
    type: String,
    default: 'Null'
  },
  courseKey: {
    type: String,
    default: 'Null'
  }
});

const emit = defineEmits(['handleDragEnd'])

function handleDragStart (e) {
  const tar = e.target;
  tar.style.opacity = '.6'; 
}

function handleDragEnd (e) {
  const tar = e.target;
  tar.style.opacity = '1';

  emit('handleDragEnd', tar);
}
</script>

<style lang="scss">
  .course-panel {
    position: relative;
    width: 150px;
    height: 100px;
    background-color: orange;
    margin: 10px auto;
    padding: 10px;
    box-sizing: border-box;
    cursor: move;

    h1 {
      font-size: 20px;
      font-weight: normal;
      text-align: center;
    }

    .remove-btn {
      position: absolute;
      top: 0px;
      right: 10px;
      color: #fff;
    }
  }
</style>

 

CoursePanel组件是用于展示单个课程信息的卡片。它接收两个prop:courseNamecourseKeycourseName用于展示课程名称,courseKey用于在拖拽结束后标识该课程的唯一键。

组件中使用了draggable属性来将元素设置为可拖拽,并监听了dragstartdragend事件。在拖拽开始时,handleDragStart函数会将被拖拽的课程卡片的不透明度设置为0.6。在拖拽结束时,handleDragEnd函数将不透明度恢复为1,并通过emit方法触发handleDragEnd事件,将当前课程卡片的信息传递给父组件。

vCoursePanel组件

接下来,我们来看看vCoursePanel.vue组件的代码:

<script setup>
import { ref } from 'vue';

const cellData = ref({
  '1-1': 'chinese',
  '2-5': 'english',
  '3-3': 'mathmatics'
})

export default {
  mounted (el, bindings) {
    const oRemoveBtn = el.querySelector('.remove-btn');
    const { cellData, weekday, timeSlot } = bindings.value;

    oRemoveBtn.addEventListener('click', handleRemovePanel, false);

    function handleRemovePanel () {
      delete cellData[`${ weekday }-${ timeSlot }`];
    }
  }
}
</script>

vCoursePanel组件表示时间表上的单元格。它接收一个prop:bindings.value,其中包含了时间表的位置信息(weekdaytimeSlot)以及时间表上已经安排的课程信息(cellData)。

在组件的mounted生命周期中,我们监听了remove-btn元素的点击事件,当点击删除按钮时,会从cellData对象中删除对应时间表位置的课程信息,实现了删除课程的功能。

主视图组件 CourseSchedule

我们来看看主视图组件 CourseSchedule.vue 的代码:

<template>
  <div class="board">
    <div class="left">
      <course-panel
        v-for="({ name }, key) in data.courses"
        :course-name="name"
        :course-key="key"
        @handle-drag-end="handleDragEnd"
      ></course-panel>
    </div>
    <div 
      class="right"
      @dragover="handleDragOver"
      @dragenter="handleDragEnter"
    >
      <table border="1">
        <tr>
          <th>时间段 / 星期</th>
          <th 
            v-for="(weekday, index) of data.weekday" 
            :key="index"
          >{{ weekday }}</th>
        </tr>
        <tr 
          v-for="(timeSlot, index) of data.time_slot" 
          :key="index"
        >
          <th>{{ timeSlot }}</th>
          <td 
            v-for="weekday in 7"
            :data-weekday="weekday"
            :data-time-slot="index"
          >
            <template v-if="cellData[`${ weekday }-${ index }`]">
              <course-panel
                :course-name="data.courses[cellData[`${ weekday }-${ index }`]].name"
                :course-key="cellData[`${ weekday }-${ index }`]"
                v-course-panel="{
                  cellData,
                  weekday,
                  timeSlot: index
                }"
              ></course-panel>
            </template>
          </td>
        </tr>
      </table>
    </div>
  </div>
</template>

<script setup>
import CoursePanel from './CoursePanel';
import vCoursePanel from './vCoursePanel';
import { ref } from 'vue';

const data = {
  weekday: [
    "星期一",
    "星期二",
    "星期三",
    "星期四",
    "星期五",
    "星期六",
    "星期日"
  ],
  time_slot: [
    "08:00-08:50",
    "09:00-09:50",
    "10:00-10:50",
    "11:00-11:50",
    "14:00-14:50",
    "15:00-15:50",
    "16:00-16:50",
    "17:00-17:50"
  ],
  courses: {
    chinese: {
      name: "语文",
      teachers: [
        "张三",
        "李四"
      ]
    },
    mathmatics: {
      name: "数学",
      teacher: [
        "王五",
        "赵六"
      ]
    },
    english: {
      name: "英语",
      teacher: [
        "野田生",
        "小夏"
      ]
    }
  }
}

/**
 * weekday
 * timeSlot
 * 
 * {
 *   1-5: chinese / english / mathmatics
 * }
 */

let targetCell = null;

const cellData = ref({
  '1-1': 'chinese',
  '2-5': 'english',
  '3-3': 'mathmatics'
})


function handleDragOver (e) {
  e.preventDefault();
}

function handleDragEnter (e) {
  e.preventDefault();
  const tar = e.target;
  const tagName = tar.tagName.toLowerCase();

  targetCell = tagName !== 'td' ? null : tar;
}

function handleDragEnd (target) {
  if (targetCell) {
    const weekday = targetCell.dataset.weekday;
    const timeSlot = targetCell.dataset.timeSlot;
    const prop = `${ weekday }-${ timeSlot }`;

    if (!cellData.value[prop]) {
      const key = target.dataset.key;
      cellData.value[prop] = key;
    }
  }
}
</script>

<style lang="scss">
.board {
  position: relative;
  
  .left {
    position: absolute;
    top: 0;
    left: 0;
    width: 300px;
    height: 100%;
  }

  .right {
    width: 100%;
    height: 800px;
    padding-left: 300px;
    box-sizing: border-box;

    table {
      width: 100%;
      border-collapse: collapse;
      table-layout: fixed;

      td {
        height: 100px;
      }
    }
  }
}
</style>

CourseSchedule.vue组件是我们的主视图组件,它包含了课程表的整体布局。在模板中,我们使用了v-for指令渲染左侧的课程卡片和右侧的时间表单元格。

左侧的div.left中,我们通过v-for遍历data.courses,渲染每门课程对应的CoursePanel组件。@handle-drag-end事件监听课程卡片的拖拽结束,当拖拽结束时,我们将调用handleDragEnd函数处理拖拽事件,将课程卡片的信息传递给主组件。

右侧的div.right是时间表的展示区域。我们使用了table标签来创建表格,并通过v-for指令渲染每个时间段和星期的单元格。在单元格内,我们使用v-if条件渲染,检查该位置是否已经有课程,如果有,则显示相应的课程卡片。

script setup中,我们引入了CoursePanelvCoursePanel组件,同时定义了时间表的数据data和已安排课程的信息cellData。我们还定义了处理拖拽事件的函数handleDragOverhandleDragEnterhandleDragEnd,用于实现课程的拖拽和安排。

效果图:

学习自B站up主:前端小野森森

总结

在这篇技术博客中,我们介绍了一个用Vue实现的『卡片拖拽式课程表』。我们逐步讲解了CoursePanel组件和vCoursePanel组件的实现,以及主视图组件CourseSchedule的布局和逻辑。通过拖拽课程卡片到时间表上,我们可以方便地安排不同课程在不同时间段的上课时间。这个简单而实用的课程表可以用于学校、培训机构等教育场景,提高课程管理的效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/811215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mac使用brew切换node的版本号

借用的是这篇文章 》 mac 使用brew切换node版本 # 查看node的版本号 brew search node# 安装其他版本. 选择 node16版本 brew install node16# 如果你是第一次安装node的话&#xff0c;执行下面这个操作 brew link --overwrite --force node16# 如果你是第二次安装node的话&am…

一文教会你单向链表

目录 一、什么是链表&#xff1f; 1.链表的定义 2.链表的实现 2.1链表的定义 2.2创建一个链表 二、链表的各个接口 1.创建节点 2.头插(将新创建的节点作为头插入到链表中) 3.打印链表 4.尾插(将新创建的节点插入到链表的末端) 5.头删 6.尾删 7.查找 8.删除指定节点位…

C语言基础入门详解三

前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。 &#x1f449;点击跳转到教程 一、C语言之函数指针 #include<stdio.h> #include<stdlib.h> /**函数指针 …

基于BIM+AI的建筑能源优化模型【神经网络】

推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 AEC&#xff08;建筑、工程、施工&#xff09;行业的BIM 技术&#xff0c;允许在实际施工开始之前虚拟地建造建筑物&#xff1b; 这带来了许多有形和无形的好处&#xff1a;减少成本超支、更有效的协调、增强决策权等等。…

实例026 随机更换主界面背景

实例说明 如果开发的软件用户使用频率非常高&#xff0c;可以为程序设计随机更换背景的程序。这样不但可以使用户心情愉快&#xff0c;也增加了软件的人性化设计。下面的界面就是一个随机更换主界面的例子&#xff0c;效果如图1.26所示。 技术要点 随机更换主界面背景使用了…

MySql002——关系型数据库基础知识

前言&#xff1a;因为本专栏学习的是MySQL&#xff0c;而MySQL是关系型数据库&#xff0c;所以这篇文章就来介绍一些关系型数据库基础知识&#xff0c;至于其他知识小伙伴们可以自行学习&#xff0c;同时不足之处也欢迎批评指正&#xff0c;谢谢~ 一、MySQL关系型数据库(RDBMS)…

Flowable-服务-Http任务

目录 定义图形标记XML内容界面操作 定义 Http 任务不是 BPMN 2.0 规范定义的官方任务&#xff0c;在 Flowable 中&#xff0c;Http 任务是作为一种特殊的服务 任务来实现的&#xff0c;主要调用Http服务使用。 图形标记 由于 Http 任务不是 BPMN 2.0 规范的“官方”任务&…

05-向量的意义_n维欧式空间

线性代数 向量与其运算 向量是线性代数里面最基本的概念&#xff0c;它其实就是一维数组&#xff0c;由 N 个数构成的&#xff0c; X(X1, X2…Xn) 向量的维度可以是任意正整数&#xff0c;可以表示在 n 维空间中的位置或方向。向量本身是一维的&#xff0c; 但向量所处的空间…

JavaWeb+jsp+Tomcat的网上订餐项目

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88130029?spm1001.2014.3001.5503 技术&#xff1a;ssm jsp JDK1.8 MySQL5.7 Tomcat7.0.5 功能&#xff1a;普通用户与管理员两个登录&#xff0c;管理员可以进行商品的增删改&#xff0c;…

JAVA SE -- 第十二天

&#xff08;全部来自“韩顺平教育”&#xff09; 常用类 一、包装类 1、包装类的分类 ①针对八种基本数据类型相应的引用类型--包装类 ②有了类的特点&#xff0c;就可以调用类中的方法 ③ 基本数据类型包装类booleanBooleancharCharacterbyteByteshortShortintInteger…

基于STM32设计的人体健康检测仪

一、项目介绍 当前文章介绍基于STM32设计的人体健康检测仪。设备采用STM32系列MCU作为主控芯片&#xff0c;配备血氧浓度传感器&#xff08;使用MAX30102血氧浓度检测传感器&#xff09;、OLED屏幕和电池供电等外设模块。设备可以广泛应用于医疗、健康等领域。可以帮助医生和病…

Spring源码(三)Spring Bean生命周期

Bean的生命周期就是指&#xff1a;在Spring中&#xff0c;一个Bean是如何生成的&#xff0c;如何销毁的 Bean生命周期流程图 1、生成BeanDefinition Spring启动的时候会进行扫描&#xff0c;会先调用org.springframework.context.annotation.ClassPathScanningCandidateCompo…

【C++入门到精通】C++入门 —— 类和对象(了解类和对象)

目录 一、类和对象的历史由来 二、面向过程和面向对象的初步认识 三、类 1.引子 2.类的定义 3.类的访问限定符及封装 ⭕访问限定符 &#x1f6a9;访问限定符解释说明 &#x1f6a9;struct 与 class 的区别 1. 默认访问级别&#xff1a; 2. 继承权限&#xff08;默认的…

安全基础 --- html标签 + 编码

html标签 &#xff08;1&#xff09;detail标签 <details>标签用来折叠内容&#xff0c;浏览器会折叠显示该标签的内容。 <1> 含义&#xff1a; <details> 这是一段解释文本。 </details> 用户点击这段文本&#xff0c;折叠的文本就会展开&#x…

山西电力市场日前价格预测【2023-07-31】

日前价格预测 预测明日&#xff08;2023-07-31&#xff09;山西电力市场全天平均日前电价为294.49元/MWh。其中&#xff0c;最高日前电价为318.11元/MWh&#xff0c;预计出现在19: 30。最低日前电价为278.89元/MWh&#xff0c;预计出现在00: 15。 价差方向预测 1&#xff1a;实…

Git远程仓库的创建、克隆、推送和拉取

文章目录 1.前言2.远程仓库的创建3.远程仓库的克隆3.1 使用HTTPS进行克隆3.2 使用SSH进行克隆 4.远程仓库的推送5. 远程仓库的拉取 1.前言 在之前的文章中,讲解了Git的一些基本概念和常用的命令. 是时候干一件大事了-实现多人协助开发! 环境:Centos7云服务器 代码托管平台: G…

基于LSTM神经网络的BIM对象识别【BIM+AI】

BIM 模型中的一个基本数据是对象的名称&#xff0c;尤其是房间。 没有专有名称&#xff0c;人们就不可能理解模型/设计的内容。 在本文中&#xff0c;我们尝试使用 Tensorflow 构建一个基于该数据识别房间的LSTM神经网络模型。 推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D…

第一章HelloWorld

确认环境 java -version javac编写代码 public class HelloWorld{public static void main(String[] args){System.out.println("HelloWorld");} }编译运行 javac HelloWord.java编译java文件成class字节码文件 java HelloWorld运行.class字节码文件 备注 容易…

手把手教你使用stable diffusion生成自己的艺术二维码

艺术二维码制作指南 导读midjourneystable diffusion 环境准备安装stable diffusion webuisd-webui-qrcode-toolkit安装 草料二维码模型准备QR PatternQR Code MonsterIoC Lab Control Net 艺术二维码制作1. 二维码信息提取2. 使用QR Tookit生成二维码3. 下载二维码图片4. prom…

电脑维护指南:让你的战友始终高效稳定

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…