vue3自定义指令封装div拖拽功能(边界限制)

直接上代码(局部使用)

<template>
  <div v-move class="box" style="text-align: right;">
    {{ positionX }}
    {{ positionY }}
  </div>
</template>
 
<script setup lang='ts'>
import { Directive, ref } from "vue";

let positionX = ref<number>(0)
let positionY = ref<number>(0)
const vMove: Directive = {
  mounted(el: HTMLElement) {
    // let moveEl = el.firstElementChild as HTMLElement;
    let moveEl = el as HTMLElement
    const mouseDown = (e: MouseEvent) => {
      //鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离
      // console.log(e.clientX, e.clientY, "-----起始", el.offsetLeft);
      let X = e.clientX - el.offsetLeft;
      let Y = e.clientY - el.offsetTop;
      const move = (e: MouseEvent) => {
        // 获取拖拽元素的位置
        let left = e.clientX - X;
        let top = e.clientY - Y;
        positionX.value = left
        positionY.value = top

        if (left <= 0) {
          left = 0
        } else if (left >= document.documentElement.clientWidth - el.offsetWidth) {
          left = document.documentElement.clientWidth - el.offsetWidth
        }

        if (top <= 0) {
          top = 0
        } else if (top > document.documentElement.clientHeight - el.offsetHeight) {
          top = document.documentElement.clientHeight - el.offsetHeight
        }

        el.style.left = left + "px";
        el.style.top = top + "px";
      };
      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", () => {
        document.removeEventListener("mousemove", move);
      });
    };
    moveEl.addEventListener("mousedown", mouseDown);
  },
};
</script>
 
<style lang='less' scoped>
.box {
  position: fixed;
  left: 0;
  top: 0;
  width: 200px;
  height: 200px;
  border: 1px solid #ccc;
  background: red;

  .header {
    height: 20px;
    background: black;
    cursor: move;
  }
}
</style>

(全局使用)

  • 首先在 utils 文件夹下新建名为 drag.ts 的文件
    代码如下
const drag = {
  mounted(el: HTMLElement) {
    let moveEl = el as HTMLElement
    const mouseDown = (e: MouseEvent) => {
      //鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离
      // console.log(e.clientX, e.clientY, "-----起始", el.offsetLeft);
      let X = e.clientX - el.offsetLeft;
      let Y = e.clientY - el.offsetTop;
      const move = (e: MouseEvent) => {
        // 获取拖拽元素的位置
        let left = e.clientX - X;
        let top = e.clientY - Y;

        if (left <= 0) {
          left = 0
        } else if (left >= document.documentElement.clientWidth - el.offsetWidth) {
          left = document.documentElement.clientWidth - el.offsetWidth
        }

        if (top <= 0) {
          top = 0
        } else if (top > document.documentElement.clientHeight - el.offsetHeight) {
          top = document.documentElement.clientHeight - el.offsetHeight
        }

        el.style.left = left + "px";
        el.style.top = top + "px";
      };
      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", () => {
        document.removeEventListener("mousemove", move);
      });
    };
    moveEl.addEventListener("mousedown", mouseDown);
  },
}

const directives = {
  install: function (app: any) {
    app.directive('drag', drag)
  }
}
export default directives

main.ts 中

// 引入文件
import Drag from './utils/drag'
// 挂载全局
app.use(Drag)
// 使用
v-drag
<div v-drag class="box" style="text-align: right;">
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3中的自定义指令封装是一种扩展Vue的能力,允许开发者在DOM元素上添加自定义行为。下面是Vue 3中自定义指令封装的步骤: 1. 创建自定义指令:使用`app.directive`方法来创建自定义指令。该方法接受两个参数,第一个参数是指令名称,第二个参数是一个对象,包含了指令的各种钩子函数和配置选项。 2. 钩子函数:自定义指令可以通过钩子函数来定义其行为。常用的钩子函数有: - `beforeMount`:在指令绑定的元素挂载到DOM之前调用。 - `mounted`:在指令绑定的元素挂载到DOM之后调用。 - `beforeUpdate`:在指令所在组件更新之前调用。 - `updated`:在指令所在组件更新之后调用。 - `beforeUnmount`:在指令所在组件卸载之前调用。 - `unmounted`:在指令所在组件卸载之后调用。 3. 配置选项:除了钩子函数外,还可以通过配置选项来定义自定义指令的行为。常用的配置选项有: - `bind`:在指令绑定到元素时立即调用,只调用一次。 - `update`:在指令所在组件的VNode更新时调用,可能会调用多次。 - `unbind`:在指令从元素上解绑时调用,只调用一次。 下面是一个示例,演示了如何在Vue 3中封装一个自定义指令: ```javascript // 创建Vue实例 const app = Vue.createApp({}); // 创建自定义指令 app.directive('my-directive', { beforeMount(el, binding, vnode) { // 指令绑定到元素之前的操作 }, mounted(el, binding, vnode) { // 指令绑定到元素之后的操作 }, beforeUpdate(el, binding, vnode) { // 指令所在组件更新之前的操作 }, updated(el, binding, vnode) { // 指令所在组件更新之后的操作 }, beforeUnmount(el, binding, vnode) { // 指令所在组件卸载之前的操作 }, unmounted(el, binding, vnode) { // 指令所在组件卸载之后的操作 } }); // 将Vue实例挂载到DOM元素上 app.mount('#app'); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值