Vue3实现可视化拖拽标签小程序

介绍

实现功能:可视化标签拖拽,双击标签可修改标签内容

HTML结构

html 复制代码
<div class="box" v-move>
  <div class="header">标签1</div>
  <div @dblclick="startEditing" v-if="!isEditing">{{content}}</div>
  <input type="text" v-model="editedContent" @blur = 'stopEditing' v-if="isEditing">
</div>

一个大DIV包含里面存放两个DIV一个input

header为头部标签名称

内容区域绑定双击鼠标事件,触发开始修改事件(startEditing),使用v-if进行标签的显示和隐藏操作

input标签,事件绑定为修改内容,绑定获取焦点事件(@blue="stopEditing"),并且绑定和内容区域一样的变量用来控制显示隐藏,一方为显示另一方必定为隐藏

TS部分

typescript 复制代码
import { Directive, DirectiveBinding } from "vue";

const vMove: Directive<any, void> = {
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    // 创建一个变量 moveElement,表示 DOM 元素的子元素(假设这是要拖动的元素)
    const moveElement: HTMLDivElement = el.firstElementChild as HTMLDivElement;

    // 鼠标按下事件处理函数
    const mouseDown = (e: MouseEvent) => {
      // 计算鼠标相对于元素的偏移量
      const X = e.clientX - el.offsetLeft;
      const Y = e.clientY - el.offsetTop;

      // 鼠标移动事件处理函数
      const move = (e: MouseEvent) => {
        // 更新元素的位置,实现拖动效果
        el.style.left = e.clientX - X + "px";
        el.style.top = e.clientY - Y + "px";
      };

      // 添加鼠标移动事件监听器
      document.addEventListener("mousemove", move);

      // 添加鼠标松开事件监听器,用于停止拖动
      document.addEventListener("mouseup", () => {
        document.removeEventListener("mousemove", move);
      });
    };

    // 将鼠标按下事件处理函数添加到元素上
    moveElement.addEventListener("mousedown", mouseDown);
  },
};

采用自定义指令进行设置移动组件,DirectiveDirectiveBinding:这是Vue.js中用于自定义指令的一些类型和功能。自定义指令允许你在DOM元素上附加自定义行为。Directive 是自定义指令的基本类型,而 DirectiveBinding 是与指令绑定的数据的类型。

上述代码定义了一个名为 vMove 的自定义指令,它会在元素上附加拖动行为。当鼠标在 moveElement(元素的子元素)上按下时,启动拖动操作,通过鼠标移动事件更新元素的位置,并在鼠标松开时停止拖动。这个自定义指令可以在Vue.js应用中使用,将其添加到需要拖动的元素上,以实现拖拽功能。

typescript 复制代码
<script setup lang="ts">
// 导入 Vue 和自定义指令相关的模块
import { ref, Directive, DirectiveBinding } from "vue";

// 自定义指令 vMove 的实现
const vMove: Directive<any, void> = (el: HTMLElement, binding: DirectiveBinding) => {
  // 获取需要移动的 DOM 元素,假设它是传入元素的第一个子元素
  let moveElement: HTMLElement = el.firstElementChild as HTMLDivElement;
  console.log(moveElement);

  // 鼠标按下事件处理函数
  const mouseDown = (e: MouseEvent) => {
    // 计算鼠标点击位置相对于元素左上角的偏移量
    let X = e.clientX - el.offsetLeft;
    let Y = e.clientY - el.offsetTop;

    // 鼠标移动事件处理函数
    const move = (e: MouseEvent) => {
      console.log(e);
      // 更新元素的位置,实现拖动效果
      el.style.left = e.clientX - X + "px";
      el.style.top = e.clientY - Y + "px";
    };

    // 添加鼠标移动事件监听器,以便拖动元素
    document.addEventListener("mousemove", move);

    // 添加鼠标松开事件监听器,停止拖动
    document.addEventListener("mouseup", () => {
      document.removeEventListener("mousemove", move);
    });
  };

  // 将鼠标按下事件处理函数添加到移动元素上
  moveElement.addEventListener("mousedown", mouseDown);

  console.log(binding);
};

// 使用 ref 创建响应式数据
const content = ref('内容'); // 原始内容
const isEditing = ref(false); // 是否处于编辑模式
const editedContent = ref(''); // 编辑后的内容

// 进入编辑模式
const startEditing = () => {
  isEditing.value = true;
  editedContent.value = content.value; // 将原始内容设置为编辑后的内容
}

// 退出编辑模式
const stopEditing = () => {
  isEditing.value = false;
  content.value = editedContent.value; // 保存编辑后的内容
}

</script>

<template>
  <div class="box" v-move>
    <div class="header">标签1</div>
    <!-- 使用双击事件触发编辑模式 -->
    <div @dblclick="startEditing" v-if="!isEditing">{{ content }}</div>
    <!-- 编辑模式下显示输入框 -->
    <input type="text" v-model="editedContent" @blur="stopEditing" v-if="isEditing">
  </div>
</template>

<style scoped>
.box {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 200px;
  height: 200px;
  border: 3px solid;
  background: #f59c09;
  .header {
    height: 20px;
    background: #f59c09;
    color: white;
  }
}
</style>
相关推荐
bitbitDown5 分钟前
重构缓存时踩的坑:注释了三行没用的代码却导致白屏
前端·javascript·vue.js
xiaopengbc8 分钟前
火狐(Mozilla Firefox)浏览器离线安装包下载
前端·javascript·firefox
用户0165238444129 分钟前
Webpack5 入门与实战,前端开发必备技能无密
前端
小高00729 分钟前
🔥🔥🔥前端性能优化实战手册:从网络到运行时,一套可复制落地的清单
前端·javascript·面试
古夕32 分钟前
my-first-ai-web_问题记录01:Next.js的App Router架构下的布局(Layout)使用
前端·javascript·react.js
Solon阿杰35 分钟前
前端(react/vue)实现全景图片(360°)查看器
javascript·vue.js
杨超越luckly38 分钟前
HTML应用指南:利用POST请求获取上海黄金交易所金价数据
前端·信息可视化·金融·html·黄金价格
Jerry42 分钟前
Compose 中的基本布局
前端
Hilaku1 小时前
深入WeakMap和WeakSet:管理数据和防止内存泄漏
前端·javascript·性能优化
Juchecar1 小时前
常见的 HTML 标签及 CSS 选择器速查表
前端