vue3 写一个简单的拖拽指令

vue3 的指令对比vue 2的变更,官方给出两点总结(目前)

  • API 已重命名,以便更好地与组件生命周期保持一致
  • 自定义指令将由子组件通过 v-bind="$attrs

1. vue3 指令的最终api

const MyDirective = {
  beforeMount(el, binding, vnode, prevVnode) {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  beforeUnmount() {}, // 新
  unmounted() {}
}

2. 基于面向对象写的拖拽

 1 class Drap{
 2     static zIndex = 1;
 3     constructor(el,option={}){
 4         this.el = el;
 5         this.x=0;
 6         this.y=0;
 7         this.option = option;
 8         this.init();
 9     }
10     init(){
11         this.setEleStyle(this.option||{});
12         this.el.onmousedown =(e)=>{
13             this.onMouseDown(e)
14             this.el.setCapture&&this.el.setCapture() //全局捕获
15             return false
16         }
17        
18     }
19     //样式设置
20     setEleStyle(option){
21         for (const key in option) {
22             this.el.style[key] = option[key]
23         }
24     }
25 
26     //按下ele
27     onMouseDown(e){
28         let zIndex = getComputedStyle(this.el).getPropertyValue('z-index');
29         zIndex=isNaN(zIndex)?1:zIndex
30         Drap.zIndex =Drap.zIndex>zIndex?Number(Drap.zIndex)+1:Number(zIndex)+1
31         this.setEleStyle({"zIndex":Drap.zIndex,position:'fixed','cursor': 'move'})
32         this.x = e.clientX-this.el.offsetLeft;
33         this.y= e.clientY-this.el.offsetTop;
34         document.onmousemove=(e)=>this.onMouseMove(e);
35         document.onmouseup = (e)=>this.onMouseUp(e)
36     }
37     //移动move
38     onMouseMove(e){
39         let X = e.clientX-this.x
40         let Y = e.clientY-this.y;
41         if(X<10-this.el.offsetWidth){
42             X=10-this.el.offsetWidth
43         }else if(X>document.documentElement.clientWidth-10){
44             X =document.documentElement.clientWidth-10
45         }
46         if(Y<10-this.el.clientHeight){
47             Y=10-this.el.clientHeight
48         }else if(Y>document.documentElement.clientHeight-10){
49             Y =document.documentElement.clientHeight-10
50         }
51         this.el.style.left = X+'px'
52         this.el.style.top = Y+'px'
53     }
54     //释放
55     onMouseUp(e){
56         document.onmousemove = null
57         document.onmouseup =null
58         this.setEleStyle({'cursor': 'pointer'})
59         this.el.setCapture&&this.el.setCapture() //释放全局捕获
60 
61     } 
62 }

3. 将封装好的拖拽整合在指令上

//src/directive/drag.js
export const  drag = {
    mounted(el, binding) { 
        new Drap(el,binding.value||{})
    }
}

4. 导入注册在当前app 实例

//src/main.js
import {drag} from  "./directive/drag"
app.directive('drag', drag)
app.mount('#app')

5. 在组件中用

<template>
    <div>
        <div class="box" v-drag="{'zIndex':100}">1</div>
         <div class="box" v-drag>2</div>
    </div>
</template>
<style scoped>
.box{
    width: 100px;
    height: 100px;
    background: red;
}
</style>