一招教你轻松实现数据拖拽功能!

前段时间业务需求里面有通过拖拽来实现类似排班的效果,但实际业务逻辑比较复杂,数据间的关联度强,不太方便展示,这里就单独把拖拽写了一个小demo进行展示。

需求:拖动左边表格里的数据进行患者手术排台

实现思路:

1、在需要拖动的dom节点上添加以下属性和事件

:draggable="true"    // 开启拖拽

@dragover.prevent.stop // 防止事件冒泡

@dragstart="onDragleave($event, item)" // 拖拽事件开始(item:被拖拽的所有数据)

2、在目标拖拽dom节点上添加以下事件

@dragover.prevent

@dragenter.prevent

@drop="handleDrop($event, item)" // item:拖拽前绑定的的原始数据

 完整代码:

<template>
  <div class="container">
    <div class="surgicalInformation">
      <!-- 表格 -->
      <table>
        <tr>
          <td>序号</td>
          <td>姓名</td>
          <td>年龄</td>
          <td>科室</td>
        </tr>
        <tr v-for="(item, index) in tableData" :data-id="item.id" :key="item.id" :draggable="true" @dragover.prevent.stop
          @dragstart="onDragleave($event, item)">
          <td>{
   
   { index + 1 }}</td>
          <td>{
   
   { item.name }}</td>
          <td>{
   
   { item.age }} 岁</td>
          <td>{
   
   { item.department }}</td>
        </tr>

      </table>
    </div>
    <div class="shiftInformation">
      <div class="box" ref="targetBox" :data-items="item.name" v-for="item in info" :key="item.name" @dragover.prevent
        @dragenter.prevent @drop="handleDrop($event, item)">
        <div class="boxName">{
   
   { item.name }}</div>
        <div class="boxContain">
          <div style="font-weight: 700;">患者手术信息</div>
          <div class="doctor">姓名 : {
   
   { item.data.doctor }}</div>
          <div class="nurse1">年龄 : {
   
   { item.data.age }}</div>
          <div class="nurse2">科室 : {
   
   { item.data.department }}</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang='ts' name="fundataDragging">
import { ref } from 'vue'

const targetBox = ref()

// 模拟数据
let tableData = ref<any[]>([])
tableData.value = [
  {
    id: 1,
    age: 20,
    name: '王患者',
    department: '手术室',
  },
  {
    id: 2,
    age: 21,
    name: '李患者',
    department: '妇产科',
  },
  {
    id: 3,
    age: 22,
    name: '陈患者',
    department: 'ICU',
  },
  {
    id: 4,
    age: 23,
    name: '郑患者',
    department: '骨科',
  },
]

// reactive 数据更新页面不更新 数组数据实时更新需要用ref
let info = ref<any[]>([])
info.value = [
  {
    name: 'A-01',
    data: {
      doctor: '',
      nurse1: '',
      nurse2: ''
    }
  },
  {
    name: 'A-02',
    data: {
      doctor: '',
      nurse1: '',
      nurse2: ''
    }
  },
  {
    name: 'A-03',
    data: {
      doctor: '',
      nurse1: '',
      nurse2: ''
    }
  },
]

const onDragleave = (event: any, item: any) => {
  event.dataTransfer.setData("nurseInfo", JSON.stringify(item));
  console.log('---拖拽的数据---: ', item);
}

const handleDrop = (event: any, item: any) => {
  event.preventDefault();
  // 获取拖放的数据
  const data = JSON.parse(event.dataTransfer.getData('nurseInfo'));
  console.log(data, '获取被拖放的数据');
  console.log(item, '拖拽之前的原数据');
  item.data.doctor = data.name
  item.data.age = data.age
  item.data.department = data.department

  // 删除拖拽走的数据
  tableData.value.map((i: any, index: number) => {
    if (data.id == i.id) {
      tableData.value.splice(index, 1)
    }
  })
}
</script>


<style lang="scss" scoped>
.container {
  height: 100%;
  display: flex;

  .surgicalInformation {
    width: 40%;
    height: 100%;
    padding: 10px;

    table {
      border: 1px solid #000;
      width: 100%;
      height: 100%;

      tr {
        height: 50px;
        text-align: center;
        background-color: #ebf5ff;
      }

      tr:nth-child(1) {
        background-color: #33affb;
      }
    }

  }

  .shiftInformation {
    flex: 1;
    height: 100%;
    display: flex;
    justify-content: space-evenly;
    padding: 80px;

    .box {
      width: 250px;
      height: 150px;
      border: 1px solid paleturquoise;
      margin-right: 10px;
      border-radius: 20px;
      display: flex;

      .boxName {
        width: 20%;
        height: 100%;
        background-color: #33affb;
        text-align: center;
        border-radius: 20px;
        line-height: 150px;
        font-size: 20px;
        font-weight: 700;
      }

      .boxContain {
        overflow: hidden;
        display: flex;
        flex-direction: column;
        justify-content: space-evenly;
        margin-left: 20px;
        font-size: 16px;
      }

    }
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/weixin_48082900/article/details/131781412