Vue()-常用组件之vuedraggable拖拽标签组件
·
多标签中的拖拽组件
<template>
<!-- 右边,第二行:tab栏 -->
<div class="towards-box">
<div class="towards-left" @click="scrollToLeft()" title="向左滑">
<i class="el-icon-arrow-left"></i>
</div>
<!--双击打开触发:打开新增窗口 TODO-->
<div class="towards-middle" @dblclick="$parent.$refs['com-add-tab'].atOpen()"
@drop="$event.preventDefault(); $event.stopPropagation();">
<div class="tab-title-box" :style="{left: scrollX + 'px'}" @dblclick.stop="">
<vuedraggable v-model="$store.state.NavTabBar.tabList" chosen-class="chosen-tab" animation="500">
<div
v-for="tab in $store.state.NavTabBar.tabList"
:key="tab.id"
:id=" 'tab-' + tab.id "
class="tab-title"
:class=" (tab === $store.state.NavTabBar.nativeTab ? 'tab-native' : '') "
@click="$store.commit('showTab',tab)"
@contextmenu.prevent="$parent.$refs['com-right-menu'].right_showMenu(tab, $event)"
draggable="true"
@dragstart="$store.state.NavTabBar.isDrag = true; $store.state.NavTabBar.dragTab = tab"
@dragend="$store.state.NavTabBar.isDrag = false;"
>
<div>{{tab.id}}</div>
<div class="tab-title-2">
<!-- <i class="el-icon-caret-right"></i> -->
<span>{{ tab.name }}</span>
<i class="el-icon-close" v-if="!tab.hideClose" @click.stop="closeTab(tab)"></i>
</div>
</div>
</vuedraggable>
</div>
</div>
<div class="towards-right" @click="scrollToRight()" title="向右滑">
<i class="el-icon-arrow-right"></i>
</div>
</div>
</template>
<script>
import $ from 'jquery'
import draggable from 'vuedraggable'
export default {
components: {
"vuedraggable": draggable, // vuedraggable
},
data() {
return {
scrollX: 0,// 滚动条位置
}
},
methods: {
// 关闭 tab (带动画)
closeTab: function (tab, callFn) {
// homeTab不能关闭
if (tab == this.homeTab || tab.hideClose) {
return;
}
// 执行关闭动画
var div = document.querySelector('#tab-' + tab.id);
div.style.width = div.offsetWidth + 'px';
setTimeout(function () {
div.style.width = '0px';
}, 0);
// 等待动画结束
setTimeout(function () {
// 如果 tab 为当前正在显示的 tab, 则切换为前一个 tab
if (tab == this.nativeTab) {
var index = this.tabList.indexOf(tab);
var preTab = this.tabList[index - 1];
if (preTab) {
this.$store.commit('showTab', preTab);
} else {
var nextTab = this.tabList[index + 1];
this.$store.commit('showTab', nextTab);
}
}
// 从 tabList 中移除这个 tab
this.arrayDelete(this.tabList, tab);
this.arrayDelete(this.viewList, tab);
// 如果有回调
if (callFn) {
this.$nextTick(function () {
callFn();
})
}
}.bind(this), 150);
},
// 删除数组某个元素
arrayDelete: function (arr, item) {
var index = arr.indexOf(item);
if (index > -1) {
arr.splice(index, 1);
}
},
// ------------------- tab左右滑动 --------------------
// 视角向左滑动一段距离
scrollToLeft: function (scroll_width) {
var width = document.querySelector('.nav-right-2').clientWidth; // 视角宽度
this.scrollX += scroll_width || width / 8; // 视角向左滑动一段距离
// 越界检查
setTimeout(function () {
if (this.scrollX > 0) {
this.scrollX = 0;
}
}.bind(this), 200);
},
// 视角向右滑动一段距离
scrollToRight: function (scroll_width) {
var width = document.querySelector('.nav-right-2').clientWidth; // 视角宽度
var tabListWidth = document.querySelector('.tab-title-box').clientWidth; // title总盒子宽度
var rightLimit = (0 - tabListWidth + width / 2); // 右滑的极限
this.scrollX -= scroll_width || width / 8; // 视角向右滑动一段距离
// 越界检查
setTimeout(function () {
if (this.scrollX < rightLimit) {
this.scrollX = rightLimit;
}
// 同时防止左边越界
if (this.scrollX > 0) {
this.scrollX = 0;
}
}.bind(this), 200);
},
// 自动归位
scrollToAuto: function () {
// console.log('自动归位=========');
try {
// 最后一个不用归位了
// if(this.nativeTab == this.tabList[this.tabList.length - 1]){
// return;
// }
var width = document.querySelector('.nav-right-2').clientWidth; // 视角宽度
var left = document.querySelector('.tab-native').lastChild.offsetLeft; // 当前native-tilte下一个距离左边的距离
// console.log(width, left, this.scrollX);
// 如果在视图右边越界
if (left + this.scrollX > (width - 200)) {
return this.scrollToRight();
}
// 如果在视图左边越界
if (left + this.scrollX < 0) {
return this.scrollToLeft();
}
} catch (e) {
// throw e;
}
},
// 让鼠标滚轮变为横向滚动
initScroll: function () {
var scroll_width = 60; // 设置每次滚动的长度,单位 px
var scroll_events = "mousewheel DOMMouseScroll MozMousePixelScroll"; // 鼠标滚轮滚动事件名
$('.towards-middle').on(scroll_events, function (e) {
var delta = e.originalEvent.wheelDelta; // 鼠标滚轮滚动度数
// 滑轮向上滚动,滚动条向左移动,scrollleft-
if (delta > 0) {
this.scrollToLeft(scroll_width);
}
// 滑轮向下滚动,滚动条向右移动,scrollleft+
else {
this.scrollToRight(scroll_width);
}
}.bind(this));
}
},
created() {
this.$nextTick(function () {
this.initScroll();
})
}
}
</script>
<style scoped>
.towards-box > div {
height: 100%;
position: absolute;
}
.towards-left, .towards-right {
width: 24px;
text-align: center;
background-color: #FFF;
cursor: pointer;
}
.towards-left {
border-right: 1px #fff solid;
}
.towards-right {
border-left: 1px #fff solid;
right: 0px;
}
.towards-left:hover i, .towards-right:hover i {
font-weight: 700; /* font-weight: bold; */
}
.towards-middle {
width: 10000px;
overflow: auto; /* calc(100% - 50px) */
left: 25px;
background-color: #FFF;
}
.tab-title-box {
display: inline-block;
position: absolute;
left: 0px;
transition: all 0.2s;
}
.tab-title {
font-size: 12px;
cursor: pointer;
float: left;
white-space: nowrap;
overflow: hidden;
text-decoration: none;
color: #333;
}
.tab-title-2 {
padding: 0px 10px; /* background-color: #FFF; */
}
.tab-title-2 {
transition: padding 0.1s, margin 0.1s;
}
/* .tab-title .el-icon-caret-right{color: #EEE; font-size: 1.7em; position: relative; top: 4px;} */
.tab-title .el-icon-close {
display: inline-block;
border-radius: 50%;
padding: 1px;
color: #ccc;
margin-left: -8px;
}
.tab-title .el-icon-close:hover {
background-color: red;
color: #FFF;
}
.tab-title span {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
}
.tab-title:hover span, .tab-native span { /* font-weight: bold; */
}
/* 卡片样式 */
/* .tab-title-box>div{line-height: 35px;} */
.tab-title {
transition: width 0.2s, background 0s, border 0.2s;
}
.tab-native {
transition: width 0.2s, background 0.2s, border 0.2s;
}
.tab-title {
border-radius: 1.5px;
border: 1px #e5e5e5 solid;
line-height: 28px;
height: 27px;
margin: 3px 1.5px;
background-color: #fff;
}
/* .tab-title.tab-native{border: 1px #409EFF solid; background-color: #409EFF; color: #fff; }
.tab-title:hover{border: 1px #409EFF solid;} */
/* .chosen-tab .tab-title-2{background-color: red;} */
</style>
/**
* 主页-顶部Tab栏
*
*/
const state = {
isDrag: false, // 当前是否正在拖拽 tab
dragTab: null, // 当前正在拖拽的 tab
tabList: [
{
id: 'home', // 唯一标识
name: '首页',
url: 'demo.html', // 页面地址
view: "",
isNeedLoad: false, // 标注:是否需要此刻加载
hideClose: true // 隐藏关闭键
}
], // 当前 Tab 集合
nativeTab: {
id: 'home', // 唯一标识
name: '首页',
url: 'demo.html', // 页面地址
view: "",
isNeedLoad: false, // 标注:是否需要此刻加载
hideClose: true // 隐藏关闭键
}, // 当前正显示的Tab
};
const getters = {};
const mutations = {};
const actions = {};
const modules = {};
export default {
state,
getters,
mutations,
actions,
modules
}
更多推荐



所有评论(0)