vue中的 拖拽

news2025/5/15 18:22:36

拖拽总结

实现方式特点适用场景
HTML5 原生拖拽 API✅ 直接使用 dataTransfer 进行数据传输
✅ 兼容性好(大部分浏览器支持)
✅ 适合简单的拖拽场景
低代码平台、表单生成器、组件拖拽
Vue/React 组件库(如 Vue Draggable、SortableJS)✅ 提供更丰富的交互效果
✅ 支持列表排序、拖拽嵌套
❌ 依赖额外的库
复杂拖拽,如列表排序、树状结构
CSS 仅视觉拖拽(无交互)✅ 仅改变视觉位置,无数据交互
❌ 无法存储拖拽数据
简单 UI 动画

目录

拖拽总结

HTML5 原生拖拽API(Drag and Drop API)

 相关代码知识点:

e.dataTransfer.setData(format, data):

e.dataTransfer.effectAllowed = 'copy';   设置拖拽的效果,表示拖拽的操作类型:

@dragover.prevent

@drop="onDropCanvas"

e.dataTransfer.getData('text/plain');:获取拖拽的数据(之前 dragstart 事件 setData 的数据)。

JSON.parse(itemData);:解析 JSON 数据,得到组件信息。

例子 —— 简易拖拽代码(H5: dataTransfer.setData + store 维护数据)

本例分析:

拖拽流程:

两种拖拽方式:


HTML5 原生拖拽API(Drag and Drop API)

分为:拖拽源 和 拖拽目标。适用于vue低代码开发。(若要 拖拽嵌套 或 复杂排序,考虑 Vue Draggable(基于 SortableJS))

拖拽源 -> 拖拽开始dragstart

  • 设置 dataTransfer.setData() 存储拖拽的数据。

  • 设置 effectAllowed 允许的拖拽行为。

  • draggable="true":启用 HTML5 拖拽。

  • @dragstart 触发 onDragStart(),存储数据。

  • e.dataTransfer.setData('text/plain', JSON.stringify(item))drop 端获取拖拽的数据。

拖拽过程中dragover)——(事件:dragover,即 拖拽对象悬停在目标上时触发)

  • 必须 preventDefault(),否则 drop 事件不会触发

拖拽目标 -> 拖拽结束drop

  • 读取 dataTransfer.getData() 获取拖拽的数据。

  • 在目标区域渲染组件。

  • @dragover.prevent阻止默认行为,允许 drop 触发。(默认情况下,浏览器不允许drop)

  • @drop="onDropCanvas":处理组件释放到画布的逻辑。

  • e.dataTransfer.getData('text/plain') 读取拖拽的数据。

  • canvasComponents.value.push() 添加组件到画布。

 相关代码知识点:
  • e.dataTransfer.setData(format, data)
    • 作用:设置拖拽时传输的数据,这样在 drop 事件时可以取回。

    • text/plain:表示数据格式为纯文本字符串(不同浏览器可能要求必须是文本格式)。

    • JSON.stringify(item):将 item(对象)转换为字符串存储,方便 drop 事件解析。

        ⚠ 注意:不设置 setData,某些浏览器可能无法正确触发 drop 事件。

  • e.dataTransfer.effectAllowed = 'copy';   设置拖拽的效果,表示拖拽的操作类型:
    • 'copy':表示复制(不会影响原始数据)。

    • 'move':表示移动(可能会删除原始数据)。

    • 'link':表示创建链接

  • @dragover.prevent
    • 事件:dragover(拖拽对象悬停在目标上时触发)。

    • prevent:阻止默认行为(默认情况下,浏览器不允许 drop)。

  • @drop="onDropCanvas"
    • 事件:drop(用户松开鼠标时触发)。

    • 作用:获取拖拽的数据;将组件添加到画布;更新 UI 状态。

  • e.preventDefault();:避免浏览器默认行为(如打开文件)。

  • e.dataTransfer.getData('text/plain');:获取拖拽的数据(之前 dragstart 事件 setData 的数据)。
  • JSON.parse(itemData);:解析 JSON 数据,得到组件信息。
  • store.addComponentToCanvas(component);:将组件添加到画布中。


例子 —— 简易拖拽代码(H5 dataTransfer.setData + store 维护数据)

<!-- test.vue -->
<script setup>
import e from 'cors';
import { store } from './store.js';

const componentList  = [
    { id: 1, type: 'Container' },
    { id: 2, type: 'Text'},
];
// 拖拽开始事件
const onDragStart = (e, item) => {
    e.dataTransfer.setData('text/plain', JSON.stringify(item)); // 设置拖拽开始 传输的数据,纯文本 字符串,将 item 对象 转为字符串存储,便于后续drop解析
    e.dataTransfer.effectAllowed = 'copy';      // 拖拽效果,拖拽类型。copy 指 复制,不影响原数据;move,表 移动,可能会删原数据;link,表示创建链接
    store.setDragItem(item, true);   // 记录当前正在拖拽的组件信息。true表示从组件库拖拽。(区分,从组件库 拖拽,和 画布内拖拽)
}  

const onDropCanvas = () => {
    // const itemData = e.dataTransfer.getData('text/plain');   // 获取拖拽的数据
    // if(!itemData) return;
    // const item = JSON.parse(itemData);  // 将字符串转为对象
    console.log("drop拖拽开始")
    store.dropToCanvas(null);
}
</script>
<template>
    <div class="app1">
        <h3>组件库(可拖动)</h3>
        <div 
            v-for="(item, index) in componentList"
            :key="item.id"
            class="draggable-item"
            draggable="true"
            @dragstart="onDragStart($event, item)"
        >
            {{ item.type }}
        </div>
        <h3>画布区域</h3>
        <div class="canvas"
            @dragover.prevent
            @drop="onDropCanvas"
        >
        <!--@dropover.prevent 阻止默认行为。(默认情况下,浏览器不允许drop)  -->
            <div v-for="(item, index) in store.treeData" :key="item.id" class="draggable-item">
                {{ item.type }}-{{ item.id }}
            </div>
        </div>
    </div>
</template>
<style scoped lang='scss'>
.app1 {
    padding: 20px;
    .draggable-item {
        border: 1px solid #ccc;
        text-align: center;
        width: 300px;
        height: 100px;
        line-height: 100px;
        background:pink;
    }
    .canvas {
        border: 2px dashed #ccc;
        width: 500px;
        height: 300px;
        margin-top:20px;
        // background: skyblue;
    }
}
</style>
// store.js
import { reactive } from 'vue'
export const store = reactive({
    treeData: [],   // 画布中的组件数据
    dragItem: null, // 当前拖拽的组件
    isRawComponents: false,   // 是否是组件库的
    
    // 设置当前拖拽的组件
    setDragItem(item, isRawComponents = false){
        this.dragItem = item;
        this.isRawComponents = isRawComponents;
        console.log("设置当前拖拽的组件。")
    },

    // 拖拽到画布中
    dropToCanvas() {
        if(!this.dragItem) return;

        const newItem = {
            id: Date.now(),
            type: this.dragItem.type,
            children: [],   // 支持未来qiantao
        };

        this.treeData.push(newItem);
        console.log("拖拽到画布。")
        this.dragItem = null;   // 清空拖拽数据
    }
})

本例分析:

通过 全局 store 维护了拖拽数据,而不是使用 dataTransfer.getData 来获取拖拽数据。

  • onDragStart 事件

    • 当用户开始拖拽组件库中的组件时,会执行 onDragStart 方法。

    • onDragStart 里除了使用 e.dataTransfer.setData 之外,还调用了 store.setDragItem(item, true),这个方法的作用是在全局的 store 里记录当前拖拽的组件信息,并标记它是从组件库拖拽的(true)。

  • onDropCanvas 事件

    • 当拖拽到画布区域并触发 onDropCanvas 时,并没有使用 e.dataTransfer.getData 获取数据。

    • 取而代之的是 store.dropToCanvas(null);,这个方法直接从 store 里获取之前存储的 dragItem 并添加到 treeData

  • dropToCanvas 方法

    • dropToCanvas 方法检查 this.dragItem 是否存在,如果存在,就创建一个新的 newItem 并添加到 treeData

    • 这样,数据传递并没有通过 dataTransfer.getData,而是通过全局 store 变量来完成的。


拖拽流程:
  1. onDragStart(e, item)store.setDragItem(item, true); 记录拖拽的组件数据。

  2. onDropCanvas()store.dropToCanvas(null); 获取 store.dragItem 并添加到 treeData

两种拖拽方式:

dataTransfer.setDatagetData 适用于不同的页面或应用之间的数据传递,但

②在同一个 Vue 组件的状态管理下,getData部分 完全可以使用 Vue 的 store 机制来管理拖拽数据。

②用 Vue 的 store 机制来管理拖拽数据优势

  • 避免 dataTransfer.getData 只能存储字符串的限制,直接在 store 里存储对象数据,不用手动 JSON.stringifyJSON.parse

  • 数据可以跨多个事件存储,即使拖拽过程中发生变化(比如鼠标移动到不同位置),仍然可以获取正确的数据。

  • 更方便管理拖拽状态,比如可以在 store 里添加 isDragging 状态,防止意外行为。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2327207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux进程间通信(1)

1.IPC 1.什么是IPC&#xff1f; Inter Process Communication 2.进程间通信常用的几种方式 1&#xff0c;管道通信&#xff1a;有名管道&#xff0c;无名管道 2&#xff0c;信号- 系统开销小 3&#xff0c;消息队列-内核的链表 4&#xff0c;信号量-计数器 5&#xff0c;共享…

Scala相关知识学习总结3

包 - 包声明&#xff1a;和Java类似&#xff0c;作用是区分同名类、管理类命名空间。Scala包名只能含数字、字母等&#xff0c;不能数字开头、不能用关键字。 - 包说明&#xff1a;有类似Java的包管理风格&#xff0c;也有独特嵌套风格。嵌套风格有两个特点&#xff0c;一是&…

Opencv计算机视觉编程攻略-第七节 提取直线、轮廓和区域

第七节 提取直线、轮廓和区域 1.用Canny 算子检测图像轮廓2.用霍夫变换检测直线&#xff1b;3.点集的直线拟合4.提取连续区域5.计算区域的形状描述子 图像的边缘区域勾画出了图像含有重要的视觉信息。正因如此&#xff0c;边缘可应用于目标识别等领域。但是简单的二值边缘分布图…

中和农信:让金融“活水”精准浇灌乡村沃土

2025年政府工作报告首提“投资于人”概念&#xff0c;并22次提及“金融”&#xff0c;强调要着力抓好“三农”工作&#xff0c;深入推进乡村全面振兴&#xff1b;一体推进地方中小金融机构风险处置和转型发展&#xff1b;扎扎实实落实促进民营经济发展的政策措施&#xff0c;切…

背包DP总结

牛客周赛 Round 81 E.建筑入门 知识点&#xff1a;完全背包&#xff0c;完全背包的路径转移以及回溯 由题意可以推导出&#xff0c;下层麻将的数字一定大于上层数字&#xff0c;所以我们可以假设一个最基础的麻将塔&#xff0c;也就是&#xff1a; 1 2 2 3 3 3 … 形如这样的&…

Labview信号采集与多功能分析系统(可仿真)

1.摘要 《Labview信号采集与多功能分析系统》可以实时分析信号的时域特征&#xff0c;例如信号的均值、方差、峰值、峭度等。系统可以进行信号的自相关与互关分析。此系统也可以分析信号的频域特征&#xff0c;包括快速傅里叶变换后的时频特征、短时傅里叶变换STFT后的时频域特…

【电子通识】为什么电子元件的规格书常常要看英文版本

在我们查看电子器件规格书的时候&#xff0c;如果有中文版本和英文版本两种供我们选择&#xff0c;那我们常常需要查看英文版本&#xff0c;大家有想过这是为什么吗&#xff1f; 为什么英文规格书很重要&#xff1f; 电子元件规格书&#xff08;Datasheet&#xff09;常以英文版…

Scala基础知识5

面向对象 Scala 的面向对象思想和 Java 的面向对象思想和概念是一致的。 Scala 中语法和 Java 不同&#xff0c;补充了更多的功能。 1.Scala包 基本语法&#xff1a;package 包名 Scala 包的三大作用&#xff08;和 Java 一样&#xff09; 1.区分相同名字的类。 2.当类很多…

【图像处理基石】什么是RAW格式?

在图像处理中&#xff0c;RAW格式是一种未经处理、记录了相机传感器原始数据的图像文件格式。它保留了相机传感器捕捉到的全部原始信息&#xff0c;未经任何压缩或处理&#xff0c;因此被称为“原始数据”&#xff08;Raw&#xff09;。以下是关于RAW格式的详细解释&#xff1a…

AI Agent 实战:搭建个人在线旅游助手

AI Agent 实战&#xff1a;搭建个人在线旅游助手 本次实验中&#xff0c;我们将继续探索 Agent 的提示词&#xff0c;学习更加规范的提示词撰写方法。 本实验中你将掌握的知识点 使用 Dify 构建 Agent 的方法结构化的提示词撰写技巧变量的使用方法 1. 准备 在新建 Agent 之…

【JavaScript】十四、轮播图

文章目录 实现一个轮播图&#xff0c;功能点包括&#xff1a; 自动播放鼠标经过暂时播放鼠标离开继续播放点击切换按钮手动切换 div盒子嵌套先写出静态HTML&#xff0c;再使用JS来修改样式和数据&#xff0c;渲染页面&#xff1a; <!DOCTYPE html> <html lang"…

2025 全球音乐 AI 大模型对决:技术革新引领商业变革浪潮

未来的世界声音&#xff1a; 音乐产业如今正被 AI 技术推动着&#xff0c;开启一场智能革命的全新篇章。无论是旋律的诞生&#xff0c;还是工业化编曲的流程&#xff0c;AI 大模型都在以飞快的速度改变着行业的基本逻辑架构。在中国&#xff0c;昆仑万维依靠 Mureka 系列产品在…

RabbitMQ详解,RabbitMQ是什么?架构是怎样的?

目录 一,RabbitMQ是什么? 二,RabbitMQ架构 2.1 首先我们来看下RabbitMQ里面的心概念Queue是什么? 2.2 交换器Exchange 2.3 RabbitMQ是什么? 2.4 重点看下优先级队列是什么? 三,RabbitMQ集群 3.1 普通集群模式 3.2 镜像队列集群 一,RabbitMQ是什么? 假设我们程序…

Java 大视界 -- Java 大数据在智能教育自适应学习平台中的用户行为分析与个性化推荐(169)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

智能打印预约系统:微信小程序+SSM框架实战项目

微信小程序打印室预约系统&#xff0c;采用SSM&#xff08;SpringSpringMVCMyBatis&#xff09;经典框架组合。 一、系统核心功能详解 1. 智能化管理后台 ​用户数据看板​打印店资源管理​预约动态监控​服务评价系统 2. 微信小程序端 ​智能定位服务​预约时段选择​文件…

Redisson 操作 Redis Stream 消息队列详解及实战案例

目录 一、Redis Stream 概念 1.Redis消息队列-认识消息队列 2.Redis Stream特点 3.Redis Stream与RabbitMQ等消息队列的比较 二.Redis Stream基本操作命令 1.生产消息 2.消费消息 3.消费者组操作 4.确认消息处理 三、Redisson 操作 Stream 的核心 API 1. 获取流的API…

【深度学习量化交易19】行情数据获取方式比测(1)——基于miniQMT的量化交易回测系统开发实记

我是Mr.看海&#xff0c;我在尝试用信号处理的知识积累和思考方式做量化交易&#xff0c;应用深度学习和AI实现股票自动交易&#xff0c;目的是实现财务自由~ 目前我正在开发基于miniQMT的量化交易系统——看海量化交易系统。 经常使用MiniQMT的朋友都知道&#xff0c;xtquant的…

23种设计模式-结构型模式-代理

文章目录 简介问题解决方案代码核心设计要点 总结 简介 代理是一种结构型设计模式&#xff0c;让你能够提供对象的替代品或其占位符。代理控制着对于原对象的访问&#xff0c;并允许在把请求提交给对象前后进行一些处理。 问题 为什么要控制对于某个对象的访问呢&#xff1f…

Windows C++ 排查死锁

开发出来应用程序突然间卡死不动&#xff0c;如果其中是因为死锁问题卡列该如何排查 下面是一个简单的死锁例子 #include <iostream> #include <thread> #include <mutex>std::mutex a, b;void function_a() {std::lock_guard<std::mutex> _x(a);std:…

ctfshow

1&#xff0c;web517 通过输入两个单引号让查询语句正常&#xff0c;判断是什么注入&#xff0c;使用的是什么字符 然后我们通过order by 判断回显位&#xff0c;进行一个联合查询注入 获取数据库名 ctfshow的sqli-labs和本地搭建最大的不同&#xff0c;就是show的flag不在当前…