业务需求

公司有一堆tab签,每个tab签里展示对应的数据,方便拖拽更换位置实现el-tabs标签页下的el-tab-pane拖拽效果,可以使用第三方插件sortable进行实现

效果图
原位置

拖动

拖动后的位置

因为csdn不会上传gif动图,所以就截取几张图片来展示实现的成果,可以看后两张红色框圈中的数据,是我按下鼠标还没放开时候的位置,证明已经实现动态拖拽。废话不多说,直接贴代码。

npm安装sortable.js

npm install sortablejs --save

小案例

<!--tabOptionList为遍历的数组 手动给el-tabs添加class,方便找到拖拽的哪一行-->
<el-tabs class="tabSign"><el-tab-panev-for="item in tabOptionList"      :key="item.name":name="item.name"       ></el-tab-pane></el-tabs>
//在script下导入
import Sortable from "sortablejs"; //插件引入data() {return {tabOptionList: ['XXX','XXXX']}},mounted() {this.rowDrop()},
//js逻辑片段(const el 必须找到自己拖拽的那一列 )
methods: {//拖拽方法rowDrop() {const el = document.querySelector(".tabSign .el-tabs__nav"); //找到想要拖拽的那一列const _this = this;Sortable.create(el, {onEnd({ newIndex, oldIndex }) {//oldIIndex拖放前的位置, newIndex拖放后的位置  //tabOptionList为遍历的tab签const currRow = _this.tabOptionList.splice(oldIndex, 1)[0]; //鼠标拖拽当前的el-tabs-pane_this.tabOptionList.splice(newIndex, 0, currRow); //tableData 是存放所以el-tabs-pane的数组},});},}

注意:

const el = document.querySelector('.tags-view-wrapper .el-scrollbar__wrap .el-scrollbar__view') // 自己项目里找到要拖拽的列。console.log(el) //打印一下,查看是否找对了

给 vue element admin 的标签视图添加拖拽功能


<template><div id="tags-view-container" class="tags-view-container"><scroll-pane ref="scrollPane" class="tags-view-wrapper" @scroll="handleScroll"><router-linkv-for="tag in visitedViews"ref="tag":key="tag.path":class="isActive(tag)?'active':''":to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"tag="span"class="tags-view-item"@click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"@contextmenu.prevent.native="openMenu(tag,$event)">{{ generateTitle(tag.title) }}<span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" /></router-link></scroll-pane><ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu"><li @click="refreshSelectedTag(selectedTag)">{{ $t('tagsView.refresh') }}</li><li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">{{ $t('tagsView.close') }}</li><li @click="closeOthersTags">{{ $t('tagsView.closeOthers') }}</li><li @click="closeAllTags(selectedTag)">{{ $t('tagsView.closeAll') }}</li></ul></div>
</template><script>
import ScrollPane from './ScrollPane'
import { generateTitle } from '@/utils/i18n'
import path from 'path'
import Sortable from 'sortablejs' // 插件引入export default {components: { ScrollPane },data() {return {visible: false,top: 0,left: 0,selectedTag: {},affixTags: []}},computed: {visitedViews() {return this.$store.state.tagsView.visitedViews},routes() {return this.$store.state.permission.routes}},watch: {$route() {this.addTags()this.moveToCurrentTag()},visible(value) {if (value) {document.body.addEventListener('click', this.closeMenu)} else {document.body.removeEventListener('click', this.closeMenu)}}},mounted() {this.initTags()this.addTags()this.rowDrop()},methods: {// 拖拽方法rowDrop() {const el = document.querySelector('.tags-view-wrapper .el-scrollbar__wrap .el-scrollbar__view') // 找到想要拖拽的那一列console.log(el)const _this = thisSortable.create(el, {draggable: '.tags-view-item',onEnd({ newIndex, oldIndex }) {// oldIIndex拖放前的位置, newIndex拖放后的位置  //visitedViews为遍历的tab签const currRow = _this.visitedViews.splice(oldIndex, 1)[0] // 鼠标拖拽当前的el-tabs-pane_this.visitedViews.splice(newIndex, 0, currRow) // tableData 是存放所以el-tabs-pane的数组}})},generateTitle, // generateTitle by vue-i18nisActive(route) {return route.path === this.$route.path},isAffix(tag) {return tag.meta && tag.meta.affix},filterAffixTags(routes, basePath = '/') {let tags = []routes.forEach(route => {if (route.meta && route.meta.affix) {const tagPath = path.resolve(basePath, route.path)tags.push({fullPath: tagPath,path: tagPath,name: route.name,meta: { ...route.meta }})}if (route.children) {const tempTags = this.filterAffixTags(route.children, route.path)if (tempTags.length >= 1) {tags = [...tags, ...tempTags]}}})return tags},initTags() {const affixTags = this.affixTags = this.filterAffixTags(this.routes)for (const tag of affixTags) {// Must have tag nameif (tag.name) {this.$store.dispatch('tagsView/addVisitedView', tag)}}},addTags() {const { name } = this.$routeif (name) {this.$store.dispatch('tagsView/addView', this.$route)}return false},moveToCurrentTag() {const tags = this.$refs.tagthis.$nextTick(() => {for (const tag of tags) {if (tag.to.path === this.$route.path) {this.$refs.scrollPane.moveToTarget(tag)// when query is different then updateif (tag.to.fullPath !== this.$route.fullPath) {this.$store.dispatch('tagsView/updateVisitedView', this.$route)}break}}})},refreshSelectedTag(view) {this.$store.dispatch('tagsView/delCachedView', view).then(() => {const { fullPath } = viewthis.$nextTick(() => {this.$router.replace({path: '/redirect' + fullPath})})})},closeSelectedTag(view) {this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {if (this.isActive(view)) {this.toLastView(visitedViews, view)}})},closeOthersTags() {this.$router.push(this.selectedTag)this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {this.moveToCurrentTag()})},closeAllTags(view) {this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {if (this.affixTags.some(tag => tag.path === view.path)) {return}this.toLastView(visitedViews, view)})},toLastView(visitedViews, view) {const latestView = visitedViews.slice(-1)[0]if (latestView) {this.$router.push(latestView.fullPath)} else {// now the default is to redirect to the home page if there is no tags-view,// you can adjust it according to your needs.if (view.name === 'Dashboard') {// to reload home pagethis.$router.replace({ path: '/redirect' + view.fullPath })} else {this.$router.push('/')}}},openMenu(tag, e) {const menuMinWidth = 105const offsetLeft = this.$el.getBoundingClientRect().left // container margin leftconst offsetWidth = this.$el.offsetWidth // container widthconst maxLeft = offsetWidth - menuMinWidth // left boundaryconst left = e.clientX - offsetLeft + 15 // 15: margin rightif (left > maxLeft) {this.left = maxLeft} else {this.left = left}this.top = e.clientYthis.visible = truethis.selectedTag = tag},closeMenu() {this.visible = false},handleScroll() {this.closeMenu()}}
}
</script><style lang="scss" scoped>
.tags-view-container {height: 34px;width: 100%;background: #fff;border-bottom: 1px solid #d8dce5;box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);.tags-view-wrapper {.tags-view-item {display: inline-block;position: relative;cursor: pointer;height: 26px;line-height: 26px;border: 1px solid #d8dce5;color: #495060;background: #fff;padding: 0 8px;font-size: 12px;margin-left: 5px;margin-top: 4px;&:first-of-type {margin-left: 15px;}&:last-of-type {margin-right: 15px;}&.active {background-color: #42b983;color: #fff;border-color: #42b983;&::before {content: '';background: #fff;display: inline-block;width: 8px;height: 8px;border-radius: 50%;position: relative;margin-right: 2px;}}}}.contextmenu {margin: 0;background: #fff;z-index: 3000;position: absolute;list-style-type: none;padding: 5px 0;border-radius: 4px;font-size: 12px;font-weight: 400;color: #333;box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);li {margin: 0;padding: 7px 16px;cursor: pointer;&:hover {background: #eee;}}}
}
</style><style lang="scss">
//reset element css of el-icon-close
.tags-view-wrapper {.tags-view-item {.el-icon-close {width: 16px;height: 16px;vertical-align: 2px;border-radius: 50%;text-align: center;transition: all .3s cubic-bezier(.645, .045, .355, 1);transform-origin: 100% 50%;&:before {transform: scale(.6);display: inline-block;vertical-align: -3px;}&:hover {background-color: #b4bccc;color: #fff;}}}
}
</style>

推荐看 很详细 -> sortable.js中文文档

vue + element 与 vue element admin 中 tab标签视图 页拖拽(拖动) sortablejs 插件案例相关推荐

  1. vue + element 中tab标签页拖拽(拖动) sortablejs插件实现

    tab签拖拽更换位置 业务需求 效果图 1.npm安装sortable.js 2.html代码块 3. 在script下导入 4.js逻辑片段(**const el 必须找到自己拖拽的那一列** ) ...

  2. 【项目技术点总结之一】vue集成d3.js利用svg加载图片实现缩放拖拽功能

    [项目技术点总结之一]vue集成d3.js利用svg加载图片实现缩放拖拽功能 前言 概述 技术介绍 实现过程 插件安装 引用组件 初始化组件 实现效果 简单理解 使用d3创建一个svg 在svg中提添 ...

  3. 计算机没鼠标怎么,计算机中没有鼠标如何进行拖拽

    计算机中没有鼠标如何进行拖拽 发布时间:2021-04-23 09:22:58 来源:亿速云 阅读:53 作者:小新 小编给大家分享一下计算机中没有鼠标如何进行拖拽,相信大部分人都还不怎么了解,因此分 ...

  4. vue+element制作音乐播放器播放进度条bug(鼠标拖拽slider滑块滑动到指定位置无效)

    最开始bug还没解决时的效果图 bug解决后的效果图 项目场景: 想自己做一个基于vue仿网易云音乐的音乐网站,在制作播放器的时候用到了element ui里面的slider组件,制作完成后发现使用c ...

  5. vue中tab标签页keep-alive二级路由+删除指定缓存页面

    1.实现效果 2.keep-alive 2.1是什么: keep-alive 是 Vue 的内置组件,keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们.和 transiti ...

  6. vue中 使用h5 drag实现拖拽功能

    先了解一下h5中的drag事件: 先贴一段代码: 先设置draggable属性为true //开始拖拽时执行 通过e.dataTransfer.setData 设置数据handleDragStart ...

  7. vue aplayer 进度条无法拖动_「最近项目小结」使用Vue实现一个简单的鼠标拖拽滚动效果插件...

    演示事例 http://www.longstudy.club/vue-drag-scroll/index.html 最近在做一个新的项目,有个需求是这样的: 简单描述一下,就是鼠标拖动页面,整个页面会 ...

  8. java 不让滚动条随着拖拽滑动_「最近项目小结」使用Vue实现一个简单的鼠标拖拽滚动效果插件...

    演示事例 http://www.longstudy.club/vue-drag-scroll/index.html 最近在做一个新的项目,有个需求是这样的: 简单描述一下,就是鼠标拖动页面,整个页面会 ...

  9. 前端项目中常用的工具包(拖拽排序表格、打印导出表格、文本复制等)【持续更新~~~】

    表格类: cdn库 cdn vxe-table[开源的多功能表格] 简介 一个基于 vue 的 PC 端表格组件,支持增删改查.虚拟滚动.懒加载.快捷菜单.数据校验.树形结构.打印导出.表单渲染.数据 ...

  10. 原生js实现canvas画布中绘制、移动、拖拽、删除矩形(如简易截图工具)

    功能描述 待图片上传并加载完成后,重新生成画布: 鼠标在画布区域内绘制,移动,拖拽,删除矩形(如截图工具一般): isboundary() 判断是否需要判断边界问题,默认false. 效果截图 实现代 ...

最新文章

  1. 建模的常用手段:组合与聚合
  2. 1.Slf4j使用log4j的配置参数、配置sl4j/log4j输出到不同的文件、案例
  3. openai-gpt_GPT-3报告存在的问题
  4. map函数作用c语言,C语言 · C++中map的用法详解
  5. 《ArcGIS Runtime SDK for Android开发笔记》
  6. MySQLdump之single-transaction详解
  7. [译] 第二天:AngularJS - 认识AngularJS
  8. 长沙理工计算机科学与技术考研,2021年长沙理工大学计算机科学与技术(081200)考研专业目录_硕士研究生考试范围 - 学途吧...
  9. LinkedList的线程安全解决办法
  10. 我是全网最硬核的高并发编程作者,CSDN最值得关注的博主,大家同意吗?(建议收藏)
  11. 【小福利】包邮送40本畅销书籍
  12. python - 乌龟吃鱼游戏
  13. 时间序列学习(5):ARMA模型定阶(AIC、BIC准则、Ljung-Box检验)
  14. html在搜索栏中加入放大镜,CSS3 搜索条动画(放大镜图标展开为长方形输入框)...
  15. 从硬件到软件,亲自动手组建家庭多媒体文件系统
  16. 软件工程(第三版) 期末复习
  17. 9.NBA球员数据分析
  18. 网易 UI 自动化工具 Airtest 浅用记录
  19. 江湖有故人!欢迎来到程序员的江湖
  20. vue路由第三篇-导航守卫、路由元信息、动态路由

热门文章

  1. windbg调试命令9(dt、d)
  2. 浪潮存储实至名归,通用存储用户评测排名全球榜首
  3. 安装VMware,出现没有虚拟网络适配器的问题
  4. 桌面版vscode用免费的微软4核8G服务器做远程开发(编译运行都在云上,还能自由创建docker服务)
  5. mysql显示1146_MySQL查询报错:ERROR 1146 (42S02): Table 'craw.sitePageConfig' doesn't exist
  6. 原生js与css3实现简单翻页动画
  7. 全国第三届SLAM技术会议记录
  8. thinkphp 运行机制和优缺点
  9. java中nextToken,Java StringTokenizer nextToken()用法及代碼示例
  10. 软件需求分析的五个步骤_建立满足用户需求的云的5个步骤