Vue2自定义拖拽指令-元素拖拽-参数传递-细节把控

70 阅读1分钟

v-canDrag

image.png

1.html部分

<template>
  <div class="drag-container">
    
    <div class="drag-div" v-canDrag="{callback:callback, desable:false}"  :style="{ left: 100 + 'px', top: 100 + 'px'}">
      top:{{ options.top }}, left:{{ options.left }}
    </div>
    
  </div>
</template>

<script>
export default {
  name: 'Nl',
  data: () => {
    return {
      options: {
        top: '100px',
        left: '100px'
      }
    }
  },
  methods:{
    callback(options){
      console.log('callback',options)
      this.options.top = options.top
      this.options.left = options.left
    }
  }
}
</script>

<style scoped lang='scss'>
.drag-container {
  width: 100%;
  height: calc(100vh - 84px);
  position: relative;
  background-color: hotpink;
}
.drag-div {
  position: absolute; /* 把拖拽元素设置为绝对定位,非常重要!!! */
  width: 100px;
  height: 100px;
  background-color: pink;
}

</style>

2. /src/directive/canDrag/index.js

export default {
  bind(el, binding, vnode) {

    //是否允许拖拽
    const desable = binding.value.desable;
    if (desable == true) return

    let _this = el; //获取当前元素
    el.onmousedown = (event) => {
      const X = event.clientX - el.offsetLeft
      const Y = event.clientY - el.offsetTop
      const maxWidth = el.parentNode.clientWidth  - el.offsetWidth
      const maxHeight = el.parentNode.clientHeight - el.offsetHeight
      
      let left, top;
      document.onmousemove = (e) => {
        //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
        left = e.clientX - X;
        top = e.clientY - Y;

        //边界限定,不允许元素超过父元素的大小
        if(left<0){
          left=0;
        }else if(left>maxWidth){
          left=maxWidth;
        }
        if(top<0){
          top=0;
        }else if(top>maxHeight){
          top=maxHeight;
        }

        el.style.left = left + "px";
        el.style.top = top + "px";
      };
      document.onmouseup = (e) => {
        document.onmousemove = null;
        document.onmouseup = null;
        // v-drag="callback";可以使用回调callback(options)获取参数
        if (binding) {
          binding.value.callback({
            id: el.id,
            top: _this.style.top,
            left: _this.style.left,
          });
        }
      };
    };
  },
};

最后注册到vue实例上就OK了