Vue『卡片拖拽式课程表』

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的布局和逻辑。通过拖拽课程卡片到时间表上,我们可以方便地安排不同课程在不同时间段的上课时间。这个简单而实用的课程表可以用于学校、培训机构等教育场景,提高课程管理的效率。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

6G内存运行Llama2-Chinese-7B-chat模型

6G内存运行Llama2-Chinese-7B-chat模型 Llama2-Chinese中文社区 第一步&#xff1a; 从huggingface下载 Llama2-Chinese-7b-Chat-GGML模型放到本地的某一目录。 第二步&#xff1a; 执行python程序 git clone https://github.com/Rayrtfr/llama2-webui.gitcd llama2-web…

QtC++ 技术分析3 - IOStream

目录 iostreamscanf/printfiostream 整体架构流相关类流缓冲区 模板特化后整体结构文件流文件流对象创建常见文件流操作输出格式设定文件流状态 字符串流字符串流内部缓冲区字符串流使用 流缓冲区用户自定义 IO iostream scanf/printf 几种常见的输入输出流函数 scanf 从键盘…

操作系统4

文件管理 文件的逻辑结构 文件的目录 文件的物理结构 文件存储空间管理 文件的基本操作

【深度学习】以图搜索- 2021sota repVgg来抽取向量 + facebook的faiss的做特征检索, 从环境搭建到运行案例从0到1

文章目录 前言安装小试牛刀用repVgg抽取向量构建Faiss索引进行相似性搜索项目延伸总结 前言 Faiss的全称是Facebook AI Similarity Search。 这是一个开源库&#xff0c;针对高维空间中的海量数据&#xff0c;提供了高效且可靠的检索方法。 暴力检索耗时巨大&#xff0c;对于…

Mac下certificate verify failed: unable to get local issuer certificate

出现这个问题&#xff0c;可以安装证书 在finder中查找 Install Certificates.command找到后双击&#xff0c;或者使用其他终端打开 安装完即可

tcp三次握手python实现和结果

下载抓包工具 安装 使用1 使用2 结果 红色笔为想要发送的数据。 代码 from scapy.all import * import logginglogging.getLogger(scapy.runtime).setLevel(logging.ERROR)target_ip = 172.20.211.4 target_port = 80 data = GET / HTTP/1.0 \r\n\r\ndef start_tcp(target_…

Mac代码编辑器sublime text 4中文注册版下载

Sublime Text 4 for Mac简单实用功能强大&#xff0c;是程序员敲代码必备的代码编辑器&#xff0c;sublime text 4中文注册版支持多种编程语言&#xff0c;包括C、Java、Python、Ruby等&#xff0c;可以帮助程序员快速编写代码。Sublime Text的界面简洁、美观&#xff0c;支持多…

上传图片到腾讯云对象存储桶cos 【腾讯云对象存储桶】【cos】【el-upload】【vue3】【上传头像】【删除】

1、首先登录腾讯云官网控制台 进入对象存储页面 2、找到跨越访问CIRS设置 配置规则 点击添加规则 填写信息 3、书写代码 这里用VUE3书写 第一种用按钮出发事件形式 <template><div><input type"file" change"handleFileChange" /><…

【设计模式】详解观察者模式

文章目录 1、简介2、观察者模式简单实现抽象主题&#xff08;Subject&#xff09;具体主题&#xff08;ConcreteSubject&#xff09;抽象观察者&#xff08;Observer&#xff09;具体观察者&#xff08;ConcrereObserver&#xff09;测试&#xff1a; 观察者设计模式优缺点观察…

DataEase开源BI工具安装_数据全量_增量同步_大屏拖拽自动生成_多数据源支持_数据血缘分析---大数据工作笔记0183

我这里用的是Centos7.9安装的 可以通过uname -p来查看一下我们的电脑架构,可以看到是x86_64架构的 我们下第一个,这个是x86架构的,第二个arm架构的 然后解压到/opt/module中 然后再去重命名一下文件夹. 推荐200G 本地模式的功能比较多 推荐100G

【FPGA IP系列】FIFO的通俗理解

FPGA厂商提供了丰富的IP核&#xff0c;基础性IP核都是可以直接免费调用的&#xff0c;比如FIFO、RAM等等。 本文主要介绍FIFO的一些基础知识&#xff0c;帮助大家能够理解FIFO的基础概念。 一、FIFO介绍 FIFO全称是First In First Out&#xff0c;即先进先出。 FIFO是一个数…

C语言第十一课--------操作符的使用与分类-------基本操作

作者前言 作者介绍&#xff1a; 作者id&#xff1a;老秦包你会&#xff0c; 简单介绍&#xff1a; 喜欢学习C语言和python等编程语言&#xff0c;是一位爱分享的博主&#xff0c;有兴趣的小可爱可以来互讨 个人主页::小小页面 gitee页面:秦大大 一个爱分享的小博主 欢迎小可爱们…

7.27 作业 QT

要求&#xff1a; 结果图&#xff1a; clock.pro: QT core gui QT texttospeechgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated …

算法与数据结构(四)--排序算法

一.冒泡排序 原理图&#xff1a; 实现代码&#xff1a; /* 冒泡排序或者是沉底排序 *//* int arr[]: 排序目标数组,这里元素类型以整型为例; int len: 元素个数 */ void bubbleSort (elemType arr[], int len) {//为什么外循环小于len-1次&#xff1f;//考虑临界情况&#xf…

Power BI-云端报表定时刷新--ODBC、MySQL、Oracle等其他本地数据源的刷新(二)

ODBC数据源 一些小众的数据源无法直接连接&#xff0c;需要通过微软系统自带的应用“ODBC数据源”连接。 1.首次使用应安装对应数据库的ODBC驱动程序&#xff0c;Mysql的ODBC驱动需要手动安装 2.在web服务中进行数据源的配置 Mysql数据源 1.Powerbi与Gateway第一次连SQL…

Ansible安装部署与应用

文章目录 一、ansible简介二、ansible 环境安装部署三、ansible 命令行模块3.1 command 模块3.2 shell 模块3.3 cron 模块3.4 user 模块3.5 group 模块3.6 copy 模块3.7 file 模块3.8 hostname 模块3.9 ping 模块3.10 yum 模块3.11 service/systemd 模块3.12 script 模块3.13 m…

Staples Drop Ship EDI 需求分析

Staples 是一家美国零售公司&#xff0c;总部位于马萨诸塞州弗拉明汉&#xff0c;主要提供支持工作和学习的产品和服务。该公司于 1986 年在马萨诸塞州布莱顿开设了第一家门店。到 1996 年&#xff0c;该公司已跻身《财富》世界 500 强&#xff0c;后来又收购了办公用品公司 Qu…

Blazor前后端框架Known-V1.2.8

V1.2.8 Known是基于C#和Blazor开发的前后端分离快速开发框架&#xff0c;开箱即用&#xff0c;跨平台&#xff0c;一处代码&#xff0c;多处运行。 Gitee&#xff1a; https://gitee.com/known/KnownGithub&#xff1a;https://github.com/known/Known 概述 基于C#和Blazor…

【文献分享】动态环境下竟然能实现实时语义RGB-D SLAM??

论文题目&#xff1a;Towards Real-time Semantic RGB-D SLAM in Dynamic Environments 中文题目&#xff1a;动态环境下实时语义RGB-D SLAM研究 作者&#xff1a;Tete Ji, Chen Wang, and Lihua Xie 作者机构&#xff1a;新加坡南洋理工大学电气与电子工程学院 卡内基梅隆大…

C++赋值运算符重载

运算符重载 C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是具有特殊函数名的函数函数名字&#xff1a;关键字operator后面接需要重载的运算符符号函数模型&#xff1a;返回值类型 operator操作符(参数列表) 注意事项&#xff1a; 1 不能通过连接其他符号…