【Vue 项目】使用 vuedraggable 实现拖拽效果时遇到的问题及解决方案总结(允许 el-table 行拖拽、部分元素不允许拖拽、拖拽避免影响文字复制和输入框输入文字)

news2024/11/19 9:27:49

由于在自己的工作和学习过程中,只查看某个大佬的教程或文章无法满足自己的学习需求和解决遇到的问题,所以自己在追赶大佬们步伐的基础上,又自己总结、整理、汇总了一些资料,方便自己理解和后续回顾,同时也希望给大家带来帮助,所以才写下该篇文章。在本文中,所有参考或引用大佬们文章内容的位置,都附上了原文章链接,您可以直接前往查阅观看。在原文章内容的基础上,若无任何补充内容,同时避免直接大段摘抄大佬们的文章,该情况下也只附上了原文章链接供大家学习。本文旨在总结归纳,并希望给大家提供帮助,未用作任何商用用途。文章内容如有错误之处,望各位大佬指出。如果涉及侵权行为,将会第一时间对文章进行删除。


👉 个人博客主页 👈
📝 一个努力学习的程序猿


其他前端组件使用和踩坑记录文章,欢迎您查看:


⭐ vuedraggable
⭐ videojs 做 hls 直播流
⭐ html2canvas + jspdf 实现将页面内容生成 PDF


vuedraggable

  • 介绍
  • 简单使用
  • 问题一、拖拽避免影响文字复制和输入框输入文字
  • 问题二、ElementUI 的 el-table 进行行拖拽


介绍

在最近的开发过程中,遇到了关于拖拽排序的功能需求。在这里向大家推荐使用👉 vuedraggable 👈插件。

【图片截取自 npm - vuedraggable】
在这里插入图片描述

在查看该组件的说明时,可以看到下图中的一段英文。

【图片截取自 npm - vuedraggable】
在这里插入图片描述
对这段英文,我在这里帮大家总结一下关键信息:

1、对较早期使用的 Sortable.js 相关用法的兼容;
(由于笔者没使用过 Sortable.js,所以没什么概念。不过在文中会有使用到 Sortable 用法的功能)

2、对 Vue 相关功能的支持;

3、在拖拽的各个阶段都有对应的事件处理;

4、兼容很多常用的 UI 组件库,比如常用的 ElementUI。
(这个将在文中的使用中有所体现)

关于更详细的内容,为了避免大篇幅引用,您可以直接前往以下文章👉 中文文档 👈学习使用。基础的用法是很简单的,如没有特殊需求,参照文档即可完整实现拖拽效果。本文中的重点将是使用过程中遇到的问题,基础的使用将不再赘述。


简单使用

首先,先 npm 下载:

npm install vuedraggable --save

再次说明: 下载完成之后,参照文档即可成功使用。为了避免大篇幅引用,建议您直接参考👉文档用例👈。例子、属性、事件在文档中有详细解答。在这里就仅把完整代码粘贴一下(不要忘记在组件中导入 draggable ):

<template>
  <div>
	  <div>{{drag?'拖拽中':'拖拽停止'}}</div>
	  <!--使用draggable组件-->
	  <draggable v-model="myArray" chosenClass="chosen" forceFallback="true" group="people" animation="1000" @start="onStart" @end="onEnd">
	    <transition-group>
	      <div class="item" v-for="element in myArray" :key="element.id">{{element.name}}</div>
	    </transition-group>
	  </draggable> 
  </div>
</template>
<style scoped>
   /*被拖拽对象的样式*/
   .item {
       padding: 6px;
       background-color: #fdfdfd;
       border: solid 1px #eee;
       margin-bottom: 10px;
       cursor: move;
   } 
   /*选中样式*/
   .chosen {
       border: solid 1px #3089dc !important;
   }
</style>
<script>
//导入draggable组件
import draggable from 'vuedraggable'
export default {
  //注册draggable组件
   components: {
   	 draggable
   },
   data() {
    return { 
      drag:false,
      //定义要被拖拽对象的数组
      myArray:[
        {people:'cn',id:10,name:'www.itxst.com'},
        {people:'cn',id:20,name:'www.baidu.com'},
        {people:'cn',id:30,name:'www.taobao.com'},
        {people:'us',id:40,name:'www.yahoo.com'}
      ] 
    };
  },
  methods: {
    //开始拖拽事件
    onStart(){
       this.drag=true;
    },
    //拖拽结束事件
    onEnd(e) {
       console.log(e); // 这里将会有调整前后的 index 及其他可能需要传递给接口的信息
       this.drag=false;
    }
  }
};
</script>

简单尝试了一下,果然好用!您也可以像我下图中这样,利用相关用法,做一些样式上的改观。

在这里插入图片描述
而在开发中,也碰到了想要实现部分元素不允许拖拽的需求,实现方式也是比较简单,为了避免大篇幅引用,您可以直接前往以下文章查阅:

【vuedraggable】实现部分元素不允许拖拽

vue.draggable filter 排除不允许拖动的元素

虽然从目前来看没什么难度,不过这将可能导致以下一系列的问题,这也是本文想主要说明的内容。


问题一、拖拽避免影响文字复制和输入框输入文字

在使用的过程中将会发现,如果我们实现了拖拽效果,那么我们将不能复制其中的文字,只要鼠标一点击就会触发拖拽。同时,如果拖拽的元素涉及到了文本输入框或者选择框等需要改变信息的操作,那么也会受到拖拽的影响。

从我在网上冲浪寻找解决办法的过程中发现,似乎没有一个比较有效的办法,实现在进行拖拽的过程中,去解决这样的一个问题。如果您有更好的办法,欢迎在评论区留言分享。

不过,虽然在使用拖拽的过程中没有办法解决,但我们可以在特定的情况下,避免使用拖拽。比如:

1、我们可以不允许包含输入框的元素进行拖拽(使用上面的部分元素不允许拖拽的方法就可以解决):

在这里插入图片描述
2、我们也可以让拖拽效果只在 点击按钮后触发 或者 在每个元素前面加一个拖动的标志,从而避免文字区域或者输入框区域无法复制的问题,比如下图中是我在每个元素前面加一个拖动的标志:
在这里插入图片描述
点击按钮后触发拖拽很简单,依然可以使用 filter 的用法,比如点击按钮后,将所有元素都包含在内,再次点击按钮将所有元素排除在外。代码简单粘贴一下:

<template>
  <div>
      <el-button @click="changeForbid">点击拖拽 / 取消</el-button>
	  <!--使用draggable组件-->
	  <draggable v-model="myArray" filter=".forbid" chosenClass="chosen" forceFallback="true" group="people" animation="1000" @start="onStart" @end="onEnd">
	    <transition-group>
	      <div v-for="element in myArray" :key="element.id">
             <span :class="{ forbid: !canDrag }">{{element.name}}</span>
	      </div>
	    </transition-group>
	  </draggable> 
  </div>
</template>
<style scoped>
   /*被拖拽对象的样式*/
   .item {
       padding: 6px;
       background-color: #fdfdfd;
       border: solid 1px #eee;
       margin-bottom: 10px;
       cursor: move;
   } 
   /*选中样式*/
   .chosen {
       border: solid 1px #3089dc !important;
   }
</style>
<script>
//导入draggable组件
import draggable from 'vuedraggable'
export default {
  //注册draggable组件
   components: {
   	 draggable
   },
   data() {
    return {
      canDrag: false,
      drag:false,
      //定义要被拖拽对象的数组
      myArray:[
        {people:'cn',id:10,name:'www.itxst.com'},
        {people:'cn',id:20,name:'www.baidu.com'},
        {people:'cn',id:30,name:'www.taobao.com'},
        {people:'us',id:40,name:'www.yahoo.com'}
      ] 
    };
  },
  methods: {
    //开始拖拽事件
    onStart(){
       this.drag=true;
    },
    //拖拽结束事件
    onEnd(e) {
       console.log(e); // 这里将会有调整前后的 index 及其他可能需要传递给接口的信息
       this.drag=false;
    },
    changeForbid() {
   	   this.canDrag = !this.canDrag;
    }
  }
};
</script>

同理地,加一个拖拽的标志,从而让拖拽只在拖动这个标志的时候,才进行拖拽,也可以使用 filter 来实现。代码简单粘贴一下(更详细地可以在问题二中查看):

 <draggable v-model="myArray" filter=".forbid" chosen-class="chosen" force-fallback="true" group="people" animation="1000" @start="onStart" @end="onEnd">
     <transition-group>
         <div 
          	v-for="element in myArray" 
          	:key="element.id"
         >
           <span>拖拽按钮</span>
           <span class="forbid">{{element.name}}</span>
       </div>
     </transition-group>
 </draggable>

如果您有更好的办法,欢迎在评论区留言分享。


问题二、ElementUI 的 el-table 进行行拖拽

之前有提到 vuedraggable 也将会支持相关组件库,即通常的 ElementUI 组件也可以使用 vuedraggable (一些普通的组件:比如 el-tag、el-card 等等。当然也会有一些自带排序功能的组件,比如 el-tree)。但是,一多半的 ElementUI 组件都是内部再次封装,如果想要对它们内部的元素进行排序,用之前的用法就无法实现了。比如接下来要说的 el-table,如果用 draggable 标签包裹,那么排序的只是表格本身。如果我想排序 el-table 里面的 行 / 列 该怎么办?这时候就可以使用 Sortable.js 。

注意:看了一些文章,它们提到如果 npm vuedraggable 之后,就也可以使用 sortablejs 。因为 vuedraggable 内部包含了 sortablejs。但是由于自己的项目里下载过 sortablejs,所以为了省点事,也没有选择卸载去进行尝试。所以如果各位无法直接使用 sortablejs 那就再 npm 一下。

npm install sortablejs --save

在这里插入图片描述

相关代码(由于考虑到对行直接进行拖拽,会导致表格文字无法复制以及输入框问题,所以采用的是通过按住拖拽按钮才进行拖拽的方式。如果不想用这个方式,做一下调整就行 => handle 去掉):

<el-table
  :data="data"
  row-key="id"
>
  <el-table-column
    label="拖拽排序"
    width="80"
    align="center"
  >
    <template slot-scope="{row}">
      <i class="el-icon-rank allowDrag" style="cursor:pointer" />
    </template>
  </el-table-column>
  <el-table-column
    label="标题"
    align="center"
  >
    <template slot-scope="{row}">
      <el-input v-model="row.title" />
    </template>
  </el-table-column>
</el-table>
created() {
  // 业务场景描述行拖拽
  const tbody = document.querySelector('.el-table__body-wrapper tbody');
  const _this = this;
  Sortable.create(tbody, {
    handle: '.allowDrag',
    onEnd({ newIndex, oldIndex }) {
      console.log(newIndex, oldIndex);
    }
  })
}

参考文章如下:

Sortablejs ElementUI

实现表格列拖拽的方法 以el-table为例

如果想要了解更多用法,就需要参考相关文档了:SortableJS 中文网


以上就可以满足目前开发中,我遇到的相关需求。希望能够给您提供帮助。


由于在自己的工作和学习过程中,只查看某个大佬的教程或文章无法满足自己的学习需求和解决遇到的问题,所以自己在追赶大佬们步伐的基础上,又自己总结、整理、汇总了一些资料,方便自己理解和后续回顾,同时也希望给大家带来帮助,所以才写下该篇文章。在本文中,所有参考或引用大佬们文章内容的位置,都附上了原文章链接,您可以直接前往查阅观看。在原文章内容的基础上,若无任何补充内容,同时避免直接大段摘抄大佬们的文章,该情况下也只附上了原文章链接供大家学习。本文旨在总结归纳,并希望给大家提供帮助,未用作任何商用用途。文章内容如有错误之处,望各位大佬指出。如果涉及侵权行为,将会第一时间对文章进行删除。


👉 个人博客主页 👈
📝 一个努力学习的程序猿


其他前端组件使用和踩坑记录文章,欢迎您查看:


⭐ vuedraggable
⭐ videojs 做 hls 直播流
⭐ html2canvas + jspdf 实现将页面内容生成 PDF

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

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

相关文章

【Node.js】深度解析常用核心模块-path模块

✅ 作者简介&#xff1a;一名将要迈入大三的大学生&#xff0c;致力于提高前端开发能力 ✨ 个人主页&#xff1a;前端小白在前进的主页 &#x1f525; 系列专栏 &#xff1a; node.js学习专栏 ⭐️ 个人社区 : 个人交流社区 &#x1f340; 学习格言: ☀️ 打不倒你的会使你更强…

本地存储(Local Storage) 和 会话存储(Session Storage)

我不会告诉你任何定义和概念&#xff0c;上车&#xff0c;读完这篇博客&#xff0c;你就会对本地存储(Local Storage) 和 会话存储(Session Storage)有一个清晰的认识。 目录前提知识范例示例1&#xff1a;将键值对提供给本地存储示例2: 本地存储中设置键值对示例3: 获取空值示…

浏览器链接跳转进入小程序指定页面(适用安卓和iOS)

安卓和ios 浏览器外部链接跳转进入小程序 需求&#xff1a;用户点击链接进入小程序 第一步&#xff1a; 需要后端配合调用微信官方提供的接口方法 生成小程序的链接。 官方文档如下&#xff1a; https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/url-…

async与await异步编程

ECMA2017中新加入了两个关键字async与await 简单来说它们是基于promise之上的的语法糖&#xff0c;可以让异步操作更加地简单明了 首先我们需要用async关键字&#xff0c;将函数标记为异步函数 async function f() {} f()异步函数就是指&#xff1a;返回值为promise对象的函…

IDEA如何完美配置Servlet(适用于IDEA 2022及以下版本)

目录 准备Java文件 导入servlet-api.jar 配置Tomcat服务器 准备Java文件 1.首先新建Java项目 选择新建项目&#xff0c;构建系统选择Maven&#xff0c;点击创建 2.选择添加框架支持&#xff08;英文为Add Framework Support&#xff09; 3.选择添加web应用程序&#xff08;…

dom-to-image

前言 之前的文章&#xff1a;vue基于html2canvas和jspdf 生成pdf 、解决jspdf中文乱码问题 简单介绍了html2canvas的基本使用&#xff0c;html2canvas 只能截取可视区域&#xff0c;对于含有滚动条的无法完全截取。后来发现还有一个dom-to-image的库可以支持&#xff0c;并且能…

【C#+JavaScript+SQL Server】实现Web端考试系统 六:后台管理模块设计(附源码和资源)

需要源码和资源请点赞关注收藏后评论区留言私信~~~ 一、后台管理模块概述 在线考试系统中&#xff0c;后台管理员模块具有最高权限&#xff0c;管理员通过登录模块成功登录之后&#xff0c;可以对试题信息&#xff0c;教师信息&#xff0c;考生信息&#xff0c;考试科目信息以…

CSS渐变背景看这一篇就够了

CSS渐变背景看这一篇就够了 在我们自己设计网页的时候&#xff0c;为了好看美观&#xff0c;颜色可谓是最让人头疼的一部分。尤其是在配色上又找不到一些好看的网站。今天我就来记录一些好看的渐变式背景&#xff0c;和一些常用的颜色网站。 CSS 渐变使可以显示两种或多种指定…

Vue Admin Template关闭eslint校验,lintOnSave:false设置无效解决办法

目录 第一步&#xff1a;lintOnSave&#xff1a;false 第二步&#xff1a;修改package.json中的配置 最后一步&#xff1a; 使用Vue Admin Template 二次开发是一件非常愉悦的事情&#xff0c;可是它里面的eslint真的是十分恶心人啊&#xff0c;对此我找了很多方法都没有解决…

浏览器强缓存与协商缓存详解以及实践

"我这边把代码更新上服务器了&#xff0c;你那边看一下呢?" "我这边还有这个问题&#xff0c;你改没改哦?" "我改了啊&#xff0c;不信你看我代码......噢&#xff0c;可能是浏览器缓存问题&#xff0c; 你F5刷新一下试试&#xff0c;如果不行 就Ct…

超星章节内ppt课件下载

超星章节内课件下载 欢迎访问个人博客&#xff1a;www.xuanworld.top 前言 ​ 一般来说&#xff0c;如果老师设置超星学习通章节内的ppt加密&#xff0c;那么ppt是无法下载的&#xff0c;超星不会提供下载接口&#xff0c;但是我们可以通过网络抓包的方式来截取到pdf&#x…

vue-router控制台异常:Uncaught (in promise) Error: Redirected when going from “/“ to “/foo“

qian kun微前端在子应用的路由配置中添加了一个全局前置导航守beforeEach&#xff0c;在前置导航守卫中调用next方法时重写了路由的path&#xff0c;结果控制台每次在路由跳转时都会报异常&#xff0c;但是不影响功能。 这里&#xff0c;我们将这个场景从微前端摘出来&#xf…

uniapp登录拦截器(未登录点击其他地方跳转登录页)

项目场景&#xff1a; 例如&#xff1a;客户要求用户在未登录的情况下&#xff0c;用户只可以在底部导航栏操作&#xff0c;点击其他的的功能都要跳转到登录页面。 uni.addInterceptor拦截器 是uni-app官网提供的拦截器&#xff0c;可以利用它来实现登录拦截器&#xff0c;用户…

vue3+pinia+vuerouter4动态路由菜单

文章目录前言一、用户权限和菜单列表数据二、pinia存储数据状态共享1.创建存储用户详情的user.ts文件2.创建存储用户菜单和权限的menus.ts文件三、设置动态路由1.在router文件夹下面创建routers.ts文件2.设置前置路由守卫3.左侧导航菜单前言 最近在做一个通用后台管理系统的框架…

35.JavaScript对象和数组的解构赋值基础详解、let陷阱、函数参数解构

文章目录35.JavaScript对象和数组的解构赋值数组解构解构不改变原数组忽略数组元素可迭代对象使用解构赋值给任何变量与.entries()方法结合与Map结合变量交换多余的元素对象解构属性变量映射默认值多余的属性let陷阱多层解析函数参数解析总结35.JavaScript对象和数组的解构赋值…

HTML使用Element-UI制作管理系统页面(无需脚手架以及创建vue工程)

HTML正常使用Element-UI前言尝试经历设计附件前言 入职培训到Web前端后布置了一个制作管理系统前端页面的任务&#xff0c;任务要求包含&#xff1a; 1.页面的布局主要为左侧导航菜单栏&#xff0c;右侧为信息展示栏&#xff0c;要体现嵌套 2.点击菜单栏切换右侧信息展示时左侧…

前端在项目中使用mockjs模拟数据的增删改查

背景 在项目开发时&#xff0c;会存在前端界面已经画好了但是后端接口还在开发的情况&#xff0c;此时前端可以先根据接口文档明确自己需要的字段&#xff0c;然后使用mock模拟后端接口进行调试 安装 npm install mockjs 使用 1. 创建vue项目之后&#xff0c;新建一个mock…

基于SpringBoot的校园疫情防控系统设计与实现

1.概述 校园疫情防控系统的开发运用java技术、springboot框架&#xff0c;MIS的总体思想&#xff0c;以及Mysql等技术的支持下共同完成了该系统的开发&#xff0c;实现了校园疫情防控管理的信息化&#xff0c;使用户体验到校园疫情防控管理&#xff0c;管理员管理操作将更加方…

使用 el-table 实现树形数据懒加载、点击行展开、每次只展示一条数据(大类)以及自定义表格合计值

1. 使用 el-table 实现树形数据懒加载 实现必需条件&#xff1a; lazy :load“loadNode” :tree-props“{ children: ‘children’, hasChildren: ‘hasChildren’ }” 注意&#xff1a;特别是第3条&#xff0c;后端接口必须传给你"hasChildren"(名字可以不一样)…

Vue3的vue-router超详细使用

从零开始搭建Vue3环境&#xff08;vitetsvue-router&#xff09;&#xff0c;手拉手做一个router项目搭建vue3环境vue-router入门&#xff08;宝宝模式&#xff09;vue-router基础&#xff08;青年模式&#xff09;一。动态路由匹配1.带参数的动态路由匹配2.捕获所有路由或404 …