效果说明
导航栏页签是动态加减的,如果页签过多,宽度超过导航栏宽度时需要通过左右两个按钮来实现滚动。
1613790190979374.gif
实现原理
- ul的css样式设置为不换行(white-space:no-wrap),超出部分隐藏(overflow:hidden)
- js找到ul,然后通过scrollTo计算滚动量。
代码
<template>
<div class="com-tab">
<i class="arrow el-icon-arrow-left" @click="scrollTab('left')"></i>
<ul id="tab-menu">
<li :id="'li'+index" v-for="(item,index) in list" :key="index" :class="{
active: item[idName] === currentName,
}" @click="tabClick(index,item)">
{{item[labelName]}}
<i class="el-icon-close close" @click="tabRemove(item)"></i>
</li>
</ul>
<i class="arrow el-icon-arrow-right" @click="scrollTab('right')"></i>
</div>
</template>
<script>
export default {
props: {
list: Array,
labelName: {
type: String,
default: 'label'
},
idName: {
type: String,
default: 'id'
},
value: {},
activeName: String
},
data() {
return {
currentName: this.value || this.activeName,
offsetCount: 0,
}
},
methods: {
// 点击tab页
tabClick(index, item) {
this.setCurrentName(item.id);
this.$emit('tab-click', item)
},
// 删除tab页
tabRemove(item) {
this.$emit('tab-remove', item)
},
// 设置当前选中tab页
setCurrentName(value) {
this.currentName = value;
this.$emit('input', value);
},
// 滑动tab页签
scrollTab(direction) {
if (this.list.length === 0) return
let menu = document.querySelector('#tab-menu')
// 计算ul宽度和当前
let ulWidth = menu.clientWidth
const getWidth = (idName) => {
let li = document.querySelector(idName)
return li.clientWidth
}
let liWidth = 0
this.list.forEach((ele, index) => {
liWidth = liWidth + getWidth(`#li${index}`)
});
// 根据方向和宽度计算偏移量
if (liWidth < ulWidth) return
let distance = this.offsetCount * 100
if (direction === 'left') {
if (this.offsetCount > 0) {
this.offsetCount = this.offsetCount - 1
}
} else if (direction === 'right') {
if ((ulWidth + distance) < liWidth) {
this.offsetCount = this.offsetCount + 1
}
}
distance = this.offsetCount * 100
menu.scrollTo({
'left': distance,
'behavior': 'smooth'
})
console.log(distance)
}
},
watch: {
activeName(val) {
this.setCurrentName(val)
},
value(value) {
this.setCurrentName(value);
},
}
}
</script>
<style>
.com-tab {
padding: 0;
background: #fff;
width: 100%;
display: flex;
}
.com-tab ul {
margin: 0;
padding: 0;
width: calc(100% - 54px);
overflow: hidden;
white-space: nowrap;
}
.com-tab li {
background: #f0f8ff;
list-style: none;
position: relative;
display: inline-block;
padding: 5px 20px 5px 15px;
border: 1px solid #dad4d8;
border-right: none;
cursor: pointer;
font-size: clamp(12px, 1.1vw, 16px);
}
.com-tab li:first-child {
border-left: none;
}
.com-tab li:last-child {
border-right: 1px solid #dad4d8;
}
.com-tab li.active,
.active>.close {
background: #fff;
color: var(--primary-blue)
}
.close {
position: absolute;
top: 2px;
right: 2px;
font-size: 8px;
color: #989ba2;
}
.arrow {
font-size: 20px;
color: #989ba2;
display: inline-block;
width: 25px;
height: 30px;
border: 1px solid #dad4d8;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
</style>
网友评论