vue2实现一个自定义拖拽功能

通过自定义指令的形式来实现,

完整代码

<template>
  <div class="container">
    <el-button @click="disorderDrag">
      <span v-if="isdragTable == true"> 禁用拖拽</span>
      <span v-else>使用拖拽</span>
    </el-button>
    <div
      v-if="isdragTable"
      style="overflow: scroll;"
    >
      <div
        v-for="item in list"
        class="contentDivDrag"
        v-drag="isdragTable"
        :id="item.id"
        :key="item.id"
      >
      </div>
    </div>
    <div
      v-else
      style="overflow: scroll;"
    >
      <div
        v-for="item in list"
        class="contentDivDrag"
        :id="item.id"
        :key="item.id"
      >
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "disorderlyDrag",
  data() {
    return {
      isdragTable: false,
      list: [
        {
          id: 1,
          label: "div1",
        },
        {
          id: 2,
          label: "div2",
        },
        {
          id: 3,
          label: "div3",
        },
      ],
    };
  },
  methods: {
    disorderDrag() {
      this.isdragTable = !this.isdragTable;
    },
  },
  //局部引入拖拽自定义指令
  directives: {
    drag: {
      inserted: function (el, binding) {
        // let self = this // 上下文
        // const oDiv = el // 当前元素
        let isdragTable = false;
        let disX, disY;

        document.onselectstart = function () {
          return false;
        };

        // 在元素上添加拖拽事件
        console.log("binding", binding.value);
        el.style.pointerEvents = "auto";

        function dragStart(e) {
          // console.log('value', binding.value)
          // 使用document可以防止鼠标移动过快导致拖拽内容脱离盒子box的范围
          document.addEventListener("mousemove", dragMove);
          document.addEventListener("mouseup", dragEnd);
          if (binding.value) {
            isdragTable = true;
            // el.style.cursor = 'grabbing'
            // 鼠标按下,计算当前元素距离可视区的距离
            // disX = e.clientX
            disX = e.clientX - el.offsetLeft;
            // disY = e.clientY
            disY = e.clientY - el.offsetTop;
          }
        }
        // 鼠标移动事件
        function dragMove(e) {
          if (isdragTable == true) {
            // 通过事件委托,计算移动的距离
            const left = e.clientX - disX;
            const top = e.clientY - disY;
            // 移动当前元素
            el.style.left = left + "px";
            el.style.top = top + "px";
          }
        }
        // 鼠标松开事件
        function dragEnd(e) {
          if (binding.value) {
            isdragTable = false;
            // el.style.cursor = 'grab'
          }
        }
        el.addEventListener("mousedown", dragStart);
        // 将事件监听移除的函数存储在元素的__removeDragEvent__属性中
        el.__removeDragEvent__ = () => {
          el.removeEventListener("mousedown", dragStart);
          document.removeEventListener("mousemove", dragMove);
          document.removeEventListener("mouseup", dragEnd);
        };
      },
      unbind(el) {
        // 移除事件监听
        el.__removeDragEvent__();
        // console.log('执行')
        delete el.__removeDragEvent__;
      },
    },
  },
};
</script>

<style lang="scss" scoped>
.container {
  position: relative;
}

.contentDivDrag {
  width: 270px;
  height: 200px;
  border: 1px solid blue;
  margin: 10px;
  position: absolute;
  cursor: move;
}
</style>

功能解读:

自定义指令只会在初始的时候执行一次,即inserted方法也只会执行一次,所以当不需要使用自定义指令的时候需要对父组件进行销毁,然后会执行自定义指令中的unbind方法,drag为自定义指令的名字,使用的时候用v-drag的形式调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值