使用vue3自定义指令实现一个拖拽指令

使用vue3自定义指令实现一个拖拽指令

自定义指令-拖拽

前言

vue3正式版已经发布大半年了,咱也得紧跟时代潮流,vue3带来的很多改变,使用ts重写代码,在兼容vue2语法的基础上,增加了很多新语法,比如新增了组合api,也移除了一些旧语法

什么是自定义指令

vue提供了很多内置的指令例如 v-model,v-show,v-for 等,这些指令极大的帮助我们提示开发效率,除了这些内置指令,vue也允许我们自定义自己的指令,vue3升级后,为了更好的与组件生命周期保持一致,指令的钩子函数被重命名了

2.x语法

  • bind - 指令绑定到元素后发生。只发生一次。
  • inserted - 元素插入父 DOM 后发生。
  • update - 当元素更新,但子元素尚未更新时,将调用此钩子。
  • componentUpdated - 一旦组件和子级被更新,就会调用这个钩子。
  • unbind - 一旦指令被移除,就会调用这个钩子。也只调用一次。

3.x语法

  • created - 新的!在元素的 attribute 或事件侦听器应用之前调用。
  • bind → beforeMount
  • inserted → mounted
  • beforeUpdate:新的!这是在元素本身更新之前调用的,很像组件生命周期钩子。
  • update → 移除!有太多的相似之处要更新,所以这是多余的,请改用 updated。
  • componentUpdated → updated
  • beforeUnmount:新的!与组件生命周期钩子类似,它将在卸载元素之前调用。
  • unbind -> unmounted

实现一个拖拽指令

先创建一个vue项目,根据自己喜好配置项目,我选择的是ts

npm install -g @vue/cli
vue create my-project
复制代码

先创建一个需要拖拽的小方块

import { defineComponent } from "vue";
import "./style.scss";
export default defineComponent({
  name: "Drag",
  render() {
    return <div class="rect"></div>;
  },
});

复制代码

样式scss

.rect {
  width: 100px;
  height: 100px;
  background-color:peru;
  position: absolute;
}
复制代码

1625743340(1).jpg

clientX,clientY,offsetLeft,offsetTop

实现拖拽需要用到以下属性

  • clientX和clientY是一个只读属性,可以获取当前鼠标在客户端的水平坐标 (与页面坐标不同),如点击页面左上角为0,无论是否出现滚动条
  • offsetLeft.offsetTop 只读属性,返回当前元素相对于 HTMLElement.offsetParent 节点的左边界偏移的像素值

自定义指令局部注册

可以在当前实例上添加directives属性来实现自定义指令,先初始化一个drag指令,这样我们就可以在vue里使用v-drag

  name: "Drag",
  directives: {
    drag: {
    },
  },
复制代码

因为需要操作dom实例,所以我们使用mounted这个钩子函数,并给当前el添加鼠标按下事件,并记录当前鼠标按下坐标mouseXStart,mouseYStart和当前滑块距离当前父节点的偏移量rectLeft,rectTop,再按下后,我们给document添加鼠标移动事件,每次移动记录当前鼠标坐标,滑块移动的距离就是mouseXEnd - mouseXStart + rectLeft和mouseYEnd - mouseYStart + rectTop,在鼠标抬起后,将move事件清空,不然会一直移动(这里要注意的是我给document添加监听事件,是因为如果给滑块添加事件,当鼠标移动过快,鼠标移出el会出现计算错误)

export default defineComponent({
  name: "Drag",
  directives: {
    drag: {
      mounted(el: HTMLDivElement) {
        el.onmousedown = (ev) => {
          console.log(ev);
          // 鼠标按下的位置
          const mouseXStart = ev.clientX;
          const mouseYStart = ev.clientY;
          console.log("按下开始", mouseXStart, mouseYStart);
          // 当前滑块位置
          const rectLeft = el.offsetLeft;
          const rectTop = el.offsetTop;
          document.onmousemove = (e) => {
            // 鼠标移动的位置
            const mouseXEnd = e.clientX;
            const mouseYEnd = e.clientY;
            const moveX = mouseXEnd - mouseXStart + rectLeft;
            const moveY = mouseYEnd - mouseYStart + rectTop;
            console.log(rectLeft, rectTop);
            el.style["top"] = moveY + "px";
            el.style["left"] = moveX + "px";
          };
          document.onmouseup = () => {
            console.log("鼠标抬起");
            // 取消事件
            document.onmousemove = null;
          };
        };
      },
    },
  },
  render() {
    return <div class="rect" v-drag></div>;
  },
});
复制代码

这样就实现了一个简单的拖拽指令

第一次写文章,大佬们轻点喷

分类:
前端