前言

前段时间有一个朋友问我前端能否实现拖放功能,大体是用拖放来调整列表顺序。
虽然我没有做过,但我见过有这种功能这样的网站呀,所以毫不犹豫的说绝对可以实现(反正不是我写)。
谁知道才过去不到一周,我自己所就职的公司也要添加一个拖放功能,而且还升级了,比拖放改变列表顺序难度更大。。。。,没办法,做呗。
好在我在我朋友问我的时候去网上查了下资料,看到了html5中有这么一个功能。
话不多说,开始干吧。

实现方法

一、什么是拖放

菜鸟教程-拖放功能 简单来说,就是把一个元素拖到另一个地方,并完成相应的功能。
官方的教程写的已经比较详细了,但描述太过官方,阅读体验未必有那么好。

二、实现步骤

1、设置元素为可拖动

把需要拖放的元素 draggable 属性设置为 true,这个属性每个元素都有,不过默认是false

<div draggable="true"></div>

这时候尝试用鼠标拖动,发现已经可以拖动了,但会显示一个禁止的图标,这是因为没有可放置的区域。

前端实现组织架构拖拽topo 前端实现拖拽排序_前端


截图无法截取那个禁止图标

2、创建可放置的区域

创建区域也很简单,只需要在标签上添加 ondragover 和 ondrop 方法即可,表示这个区域可放置并进行处理。

<div @drop.prevent="drop" @dragover.prevent="dragover"></div>

前端实现组织架构拖拽topo 前端实现拖拽排序_vue_02

3、添加拖动方法

只需要在需要拖动的元素上添加 ondragstart 方法即可

<div draggable="true" @dragstart="dragstart()"></div>

三、完整代码

我是用vue写的demo,这样比较简洁一点,为了方便操作,我添加了删除功能,
代码如下:

<template>
  <div class="body flex">
    <div draggable="true"></div>
    <ul>
      <li
        draggable="true"
        :ref="'li' + index + 1"
        v-for="(item, index) in list"
        :key="index"
        @dragstart="dragstart(index)"
      >
        {{ item }}
      </li>
    </ul>
    <div class="box center" @drop.prevent="drop" @dragover.prevent="dragover">
      <div class="delete" @click="deleteBox()">删除</div>
      <p v-show="content">{{ text }}</p>
    </div>
  </div>
</template>

<script>
export default {
  name: "",
  components: {},
  data() {
    return {
      list: [
        "拖放内容1",
        "拖放内容2",
        "拖放内容3",
        "拖放内容4",
        "拖放内容5",
        "拖放内容6"
      ],
      text: "",
      content: false
    };
  },
  computed: {},
  watch: {},
  mounted() {},
  methods: {
    deleteBox() {
      this.content = false;
    },
    // 拖动开始
    dragstart(index) {
      this.text = "您已成功拖放元素" + (index + 1);
    },
    // 进行放置
    drop(event) {
      this.content = true;
      console.log("drop", event);
    },
    // 放置位置 - 阻止默认事件
    dragover(event) {
      event.preventDefault();
    }
  }
};
</script>
<style lang="scss" scoped>
.body {
  user-select: none; // 禁止选中文字
  margin: 20px;
  font-size: 16px;
  ul {
    li {
      border-radius: 5px;
      cursor: pointer;
      margin-bottom: 10px;
      padding: 5px 10px;
      line-height: 26px;
      background-color: rgb(221, 221, 221);
    }
  }
  .box {
    position: relative;
    margin-left: 100px;
    width: 500px;
    height: 500px;
    border: 1px solid #999;
    .delete {
      cursor: pointer;
      position: absolute;
      top: 0;
      right: 0;
      padding: 5px 10px;
      background-color: rgba(243, 89, 84, 0.3);
      border-radius: 5px 0px 5px 5px;
    }
    .delete:hover {
      color: #fff;
      background-color: rgb(243, 89, 84);
    }
    p {
      font-size: 26px;
      font-weight: bold;
      animation: light 1s linear 1;
    }
  }
  @keyframes light {
    0% {
      transform: rotate(0deg);
    }
    50% {
      transform: rotate(180deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
}
</style>
最终效果如下:

前端实现组织架构拖拽topo 前端实现拖拽排序_属性设置_03


over…