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>
相关推荐
你挚爱的强哥24 分钟前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189111 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
Jacky(易小天)3 小时前
MongoDB比较查询操作符中英对照表及实例详解
数据库·mongodb·typescript·比较操作符
天天进步20153 小时前
Vue+Springboot用Websocket实现协同编辑
vue.js·spring boot·websocket
虾球xz4 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇4 小时前
HTML常用表格与标签
前端·html