vue2实现卡片拖拽式课程表

news2024/9/23 13:28:31

目录

一、效果展示

二、代码分析

2.1、两栏布局、表格编写与课程卡片

2.2、初始化数据与渲染

2.3、拖拽卡片到表格,进行插入

2.4、自定义指令进行删除

一、效果展示

二、代码分析

主页面代码:

<template>
  <div class="board">
    <div class="left">
      <CoursePerson
        v-for="({ name }, k) in datas.courses"
        :key="k"
        :courseName="name"
        :courseKey="k"
        @handleDragEnd="handleDragEnd"
      ></CoursePerson>
    </div>
    <div class="right" @dragover="handleDragOver" @dragenter="handleDragEnter">
      <table border="1">
        <tr>
          <th>时间段 / 星期</th>
          <th v-for="(w, i) in datas.weekday" :key="i">{{ w }}</th>
        </tr>
        <tr v-for="(t, i) in datas.time_slot" :key="i">
          <th>{{ t }}</th>
          <td v-for="n in 7" :key="n" :data-weekday="n" :data-time-slot="i">
            <template v-if="cellData[`${n}-${i}`]">
              <CoursePerson
                :courseName="datas.courses[cellData[`${n}-${i}`]].name"
                :courseKey="cellData[`${n}-${i}`]"
                v-CoursePanel="{ cellData, n, timeSlot: i }"
              ></CoursePerson>
            </template>
          </td>
        </tr>
      </table>
    </div>
  </div>
</template>

<script>
import CoursePerson from "@/components/CoursePerson.vue";
export default {
  components: {
    CoursePerson,
  },
  directives: {
    // 定义名为CoursePanel的指令,指向一个配置对象
    CoursePanel: {
      bind(el, bindings) {
        const oRemoveBtn = el.querySelector(".remove-btn");
        const { cellData, n, timeSlot } = bindings.value;
        oRemoveBtn.addEventListener("click", handleRemovePanel, false);
        function handleRemovePanel() {
          delete cellData[`${n}-${timeSlot}`];
        }
      },
    },
  },
  data() {
    return {
      datas: {
        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: ["张三", "李四"],
          },
          math: {
            name: "数学",
            teachers: ["张二", "李五"],
          },
          english: {
            name: "英语",
            teachers: ["张3", "李2"],
          },
        },
      },
      cellData: {
        "1-1": "chinese",
        "2-5": "math",
        "3-3": "english",
      },
      targetCell: null,
    };
  },
  methods: {
    handleDragOver(e) {
      e.preventDefault();
    },
    handleDragEnter(e) {
      e.preventDefault();
      const tar = e.target;
      const tagName = tar.tagName.toLowerCase();
      this.targetCell = tagName != "td" ? null : tar;
    },
    handleDragEnd(e) {
      if (this.targetCell) {
        const weekday = this.targetCell.dataset.weekday;
        const timeSlot = this.targetCell.dataset.timeSlot;
        const prop = `${weekday}-${timeSlot}`;
        if (!this.cellData[prop]) {
          //给表格中没有坐标的课程
          const key = e.dataset.key;
          this.$set(this.cellData, prop, key); //借助$set赋值,更新视图
          // this.cellData[prop] = key; //赋值(vue2赋值视图不更新)
        }
      }
    },
  },
};
</script>

<style lang='less' scoped>
.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: 60px;
        text-align: center;
      }
    }
  }
}
</style>

卡片组件代码:

<template>
  <!-- draggable="true"  该盒子可被拖动 -->
  <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>
export default {
  props: ["courseName", "courseKey"],
  methods: {
    handleDragStart(e) {
      const tar = e.target;
      tar.style.opacity = ".6";
    },
    handleDragEnd(e) {
      const tar = e.target;
      tar.style.opacity = "1";
      this.$emit("handleDragEnd", tar);
    },
  },
};
</script>

<style lang='less' scoped>
.course-panel {
  position: relative;
  width: 100px;
  height: 60px;
  background-color: goldenrod;
  margin: 10px auto;
  padding: 10px;
  box-sizing: border-box;
  cursor: move;
  h1 {
    font-size: 20px;
    text-align: center;
  }
  .remove-btn {
    position: absolute;
    top: 0px;
    right: 10px;
  }
}
</style>

2.1、表格编写与课程卡片

  静态页面主要采用两栏布局。左侧为卡片组件,右侧为表格。

2.2、初始化数据与渲染

  td是单元格,现在里面是一个7X7的表格,想要将指定课程的卡片渲染上去,我们可以借助cellData变量里的值,类似二维数组,我们找到坐标,就可以渲染上去。

2.3、拖拽卡片到表格,进行插入

  拖拽效果:draggable="true"  意味着该盒子可被拖动,包括很多事件,比如:dragstart、dragend、dragover、dragenter等。

  插入实现:看似是将左侧的卡片拖进去,实则是在进入表格时(拖拽结束)进行了数据的改动,就是给cellData这个对象里继续增加一个属性和属性值,达到插入效果。vue2里直接复制,视图不会变化,可以通过$set进行视图更新this.$set(this.cellData, prop, key);

2.4、自定义指令进行删除

  本例中通过视图中  v-CoursePanel="{ cellData, n, timeSlot: i }",结合directives里的CoursePanel指令进行表格内卡片的删除。这里的删除指删除表格内的任意卡片,而不能删除左侧的原始卡片。所以组件结合自定义指令去进行删除操作。

  现在它删除有个bug,点击x删除,需要再次拖拽(添加)时,才会看到删除的卡片效果,尚待完善。。。

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

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

相关文章

【QT】枚举常用宏(Q_ENUM,Q_FLAG,Q_DECLARE_FLAGS,Q_DECLARE_OPERATORS_FOR_FLAGS)

目录 1. Q_ENUM宏 与 QMetaEnum类1.1 Q_ENUM宏的作用1.2 使用Q_ENUM注意的问题1.3 在写有关枚举的代码时&#xff0c;我们可能遇到这种情况&#xff1a;需要用到枚举的字符串&#xff0c;该怎么办&#xff1f;1.4 下面通过一段简单的代码来说明Q_ENUM的作用 2. Q_FLAG宏2.1 Q_F…

datax mysql同步数据到clickhouse配置文件样例及说明

datax mysql同步数据到clickhouse配置文件样例及说明 { "job": { "content": [ { "reader": { "parameter": { "password": "…

魔兽世界私人服务器怎么开

开设魔兽世界的私人服务器涉及到一系列复杂的步骤和技术要求。下面是一个大致的指南&#xff0c;以供参考&#xff1a; 1. 硬件需求&#xff1a;首先&#xff0c;你需要一台强大的服务器来承载游戏服务器。服务器的规模和配置将取决于你计划同时容纳多少玩家以及服务器的性能要…

linux下unmount了移动硬盘之后,硬盘灯还是常亮并且硬盘还在一直转动

linux下unmount了移动硬盘之后&#xff0c;硬盘灯还是常亮并且硬盘还在一直转动 ​ 参考:https://www.zhihu.com/question/23362385 希捷2T移动硬盘 在windows下卸载硬盘之后硬盘灯就不亮了&#xff0c;手摸也没有震动感。 在ubuntu下卸载硬盘之后&#xff0c;硬盘灯仍然常…

语音采集技术新革命,4G语音工牌问世,它有哪些应用价值?

随着ChatGpt的火爆和大语言模型的日趋成熟&#xff0c;智能语音赛道迎一轮新的发展。越来越多的企业开始着眼语音数据价值的挖掘&#xff0c;期望能借此来实现销售过程的洞察、赋能&#xff0c;服务过程的管理&#xff0c;客户的精细化运营。基于此&#xff0c;语音前端的采集工…

基于数字全息和相位恢复算法的信息加密与重建实验研究-Matlab代码

▒▒本文目录▒▒ 一、引言二、相位恢复算法三、数字全息显微加密与重建实验验证3.1 基于相位恢复算法全息图加密与解密3.2 菲涅耳变换法重建像3.3 卷积法重建像3.4 角谱法重建像 四、参考文献五、Matlab程序获取 一、引言 近年来&#xff0c;基于光学信息处理技术对图像进行加…

【期末专题】数据库知识点整理

1.要求&#xff1a;修改表的“价格”列&#xff0c;使其数据类型为decimal(6,2) 语句&#xff1a;alter table BookInfo modify price decimal(6,2); 注意点&#xff1a;修改一个表中已有列的数据类型的语句格式&#xff1a; alter table <表名> modify <列名> &…

【STM32】F103 总线结构

一、总线的概念二、STM32的总线结构2.1 STM32的总线矩阵2.2 STM32的存储器映射2.3 STM32的外设寄存器 一、总线的概念 总线是连接多个部件的信息传输线&#xff0c;是各部件共享的传输介质。总线是一种电路&#xff0c;它是CPU、RAM、ROM、输入、输出等设备传递信息的公共通道…

DYnamics 365如何隐藏实体列表页面home page页面上的PowerBI按钮和EXCEL template按钮

如何隐藏以上两个按钮&#xff0c;用ribbon工具根本找不到这2个按钮。 解决方案&#xff1a;添加一个没用的按钮&#xff0c;通过调用enable方法来隐藏。 // JavaScript source code function HiddenButton() { HiddePowerBIButton(); HiddeDocumentTemplateButton(); return…

u盘文件加密怎么设置?丢失重要数据怎么办?

“我同事经常趁我不在工位上的时候&#xff0c;拿我的U盘拷贝了一些文件资料&#xff0c;都没经过我的同意。本来U盘里就存储了很多个人数据&#xff0c;比较隐私&#xff0c;并不想被别人看见&#xff0c;我想给U盘加密&#xff0c;请问u盘文件加密怎么设置&#xff1f;有没有…

国内的“PMP证书”来了,值不值得考?(PMP证书免考增持CSPM-2)

2021年10月&#xff0c;中共中央、国务院发布的《国家标准化发展纲要》明确提出构建多层次从业人员培养培训体系&#xff0c;开展专业人才培养培训和国家质量基础设施综合教育。建立健全人才的职业能力评价和激励机制。由中国标准化协会&#xff08;CAS&#xff09;组织开展的项…

H5学习(二)-- 常用标签

标签内容 一、标题标签二、表单标签啊三、段落标签四、插入图片标签五、换行标签六、列表标签七、超链接标签八、容器标签九、结构性标签十、级块性标签十一、行内语义性标签 HTML中的常用的标签 一、标题标签 <body><!--标题标签--><h1>h1标签</h1>&…

关于vue中element-UI中table的循环展示以及分页方式

vue中table多用到分页&#xff0c;有时会忘记怎么使用分页和循环展示表格 直接上代码&#xff1a; 父组件 <tableDate :dateTable"dateTable" :tableData"tableData"></tableDate>js部分 export default {components: {searchBox,tableDate}…

sounddevice通过ffmpeg读取rstp远程网络设备声音;conda环境里用不了电脑系统环境里的应用ffmpeg

1、sounddevice通过ffmpeg读取rstp远程声音 *** samples维度是samples_per_read指定 *** ##用全路径&#xff0c;调用系统ffmpeg&#xff0c;直接conda里运行不然容易出错 C:/Users/loong/.conda/envs/nlp/python.exe D:\sound\ffmpeg_test.pyffmpeg_test.py: import sound…

Revit添加自己的快捷键和一键剪切

一、Revit中如何自己添加快捷键 我们用Revit做模型时&#xff0c;快捷键可以加快我们的操作速度&#xff0c;提高工作效率。那么我们如何自己添加快捷键呢&#xff0c;下面请看步骤。 1、 点击“视图”&#xff0c;最右“用户界面” 2、 点击“快捷键”&#xff0c;过滤器为“全…

vue2/vue3中,H5自动生成骨架屏代码

generate-skeleton-h5 vue2/vue3自动生成h5骨架屏 安装骨架屏插件 npm i draw-page-structure -D页面引入 import { generateSkeleton } from "generate-skeleton-h5" generateSkeleton().then(res > {// 当前页面的骨架屏代码&#xff0c;含html与cssconsole…

Flutter学习四:Flutter开发基础(四)包管理

目录 0 引言 1 包管理 1.1 简介 1.2 Pub仓库 1.3 依赖Pub仓库 1.3.1 查找包 1.3.2 添加包 1.3.3 下载包 1.3.4 引入包 1.3.5 使用包 1.4 其他依赖方式 1.4.1 依赖本地包 1.4.2 依赖git仓库 1.4.3 不常用的依赖方式 0 引言 本文是对第二版序 | 《Flutter实战第二版…

一文搞懂JSON

目录 什么是JSON? JSON的基本数据类型 JSON的特点和优势&#xff08;了解&#xff09; JSON格式规范&#xff08;重点&#xff09; JSON的基本操作 关键接口的梳理 序列化 反序列化 答案和解析 序列化答案 反序列化答案 第一种思路 第二种思路 什么是JSON? JSO…

Linux4.vim

1.vim 三种模式 : 命令模式的常见命令 : 底行模式 : 2.sudo 信任名单的位置 : /etc/sudoers 添加信任名单 :以root身份&#xff0c;使用vim打开信任名单&#xff0c;显示行号&#xff0c;大概在104行。

数字化车间数字孪生可视化提高资产利用率

车间管理中往往存在以下几方面问题&#xff1a; 1、产品加工过程复杂、工序繁多;产品在生产制造过程中由于设备和工艺等原因产生不确定因素会影响最终产品质量; 2、生产计划制定困难、生产任务无法及时完成导致生产计划执行困难; 3、业务需求不明确或变化频繁造成车间管理工作无…