vue實(shí)現(xiàn)tab標(biāo)簽(標(biāo)簽超出自動(dòng)滾動(dòng))
當(dāng)創(chuàng)建的tab標(biāo)簽超出頁(yè)面可視區(qū)域時(shí)自動(dòng)滾動(dòng)一個(gè)tab標(biāo)簽距離,并可手動(dòng)點(diǎn)擊滾動(dòng)tab標(biāo)簽,實(shí)現(xiàn)效果請(qǐng)看GIF圖
效果預(yù)覽GIF圖
<template> <div class="main-box"> <button @click="add">添加</button> <div class="main-box-tab"> <i @click="previous"><<</i> <i @click="next">>></i> <div class="main-box-tab-content" ref="tabs"> <div class="main-box-tab-roll"> <div v-for="(item,index) in tabs" :key="index" :class="{'tab-item-action':actionName === item.name ,'tab-item':actionName !== item.name}" @click.stop="clickTab(item.name,index)"> <span>{{item.meta.title}}</span> <i class="el-icon-close" @click.stop="close(item.name)"></i> </div> </div> </div> </div> <div class="main-box-content"> <div>{{actionName}}</div> </div> </div> </template> <script> export default { name: "index", data() { return { tabs: [], moveX: 0, count: 1, unoccupied: 0, tabsCount: 0, actionName: 'test1' } }, watch: { actionName(val) { let len = this.tabs.length // 如有重復(fù)數(shù)據(jù)退出后續(xù)函數(shù)執(zhí)行 for (let i = 0; i < len; i++) { if (this.tabs[i].name === val) { this.$nextTick(() => { this.translateX((i + 1 - this.tabsCount) * this.width - this.unoccupied) }) return } } this.tabs.push({ name: `test${this.count}`, meta: { title: `test${this.count}` } }) this.$nextTick(() => { // (總共有多少個(gè)tabs - 未偏移時(shí)可見(jiàn)的元素個(gè)數(shù)) * 單個(gè)tab標(biāo)簽元素長(zhǎng)度 - 被遮擋tab元素的可見(jiàn)部分的寬度 this.translateX((this.tabs.length - this.tabsCount) * this.width - this.unoccupied) }) } }, mounted() { this.tabs.push({ name: `test${this.count}`, meta: { title: `test${this.count}` } }) this.$nextTick(() => { let tabs = this.$refs.tabs let getStyle = getComputedStyle(tabs.children[0].children[0], null) let marginLeft = parseFloat(getStyle.marginLeft.substr(0, getStyle.marginLeft.length - 2)) let marginRight = parseFloat(getStyle.marginRight.substr(0, getStyle.marginRight.length - 2)) // 元素實(shí)際寬度 = 元素的寬度 + 外邊距 this.width = marginLeft + marginRight + tabs.children[0].children[0].offsetWidth /** * 以下注釋計(jì)算方式用于理解實(shí)現(xiàn)邏輯 **/ // // 可視區(qū)域能放入多少個(gè)元素 = 可視區(qū)域的寬度 / 子元素實(shí)際寬度 // let num = tabs.offsetWidth / this.width // // 被遮擋tab元素的可見(jiàn)部分的寬度 = 可見(jiàn)區(qū)域的寬度 - (子元素實(shí)際寬度 * num轉(zhuǎn)為整數(shù)) // this.unoccupied = tabs.offsetWidth - (this.width * parseInt(num)) // 最終精簡(jiǎn)為取余(得數(shù)跟上面的計(jì)算是一樣的) this.unoccupied = tabs.offsetWidth % this.width // 轉(zhuǎn)為整數(shù) this.tabsCount = parseInt(tabs.offsetWidth / this.width) }) }, methods: { add() { this.count++ this.actionName = `test${this.count}` }, /** * 切換tab標(biāo)簽頁(yè) **/ clickTab(name) { if (this.actionName !== name) { this.actionName = name } }, /** * 關(guān)閉tab標(biāo)簽頁(yè) **/ close(name) { let len = this.tabs.length let jumpName = null if (len > 1) { for (let i = 0; i < len; i++) { if (this.tabs[i].name === name) { this.tabs.splice(i, 1) jumpName = this.tabs[i ? i - 1 : 0].name if (this.actionName !== jumpName && name === this.actionName) { this.actionName = jumpName } this.$nextTick(() => { this.previous() }) return } } } }, /** * 往右偏移 **/ next() { // scrollWidth獲取不準(zhǔn)確 // 使用this.width * this.tabs.length計(jì)算出總長(zhǎng)度 let totalWidth = this.width * this.tabs.length this.$nextTick(() => { let dom = this.$refs.tabs // 可視區(qū)域 < 滾動(dòng)區(qū)域(滾動(dòng)區(qū)域大于可視區(qū)域才可以移動(dòng)) // 移動(dòng)距離 + 可視區(qū)域 = 滾動(dòng)區(qū)域的寬度(上一次的寬度,當(dāng)點(diǎn)擊時(shí)才是實(shí)際寬度)< 滾動(dòng)區(qū)域 if (dom.clientWidth < totalWidth && this.moveX + dom.clientWidth < totalWidth) { // this.moveX為0減去空余空間的寬度 this.moveX += this.moveX ? this.width : this.width - this.unoccupied this.translateX(this.moveX) } }) }, /** * 往左偏移 **/ previous() { if (this.moveX > 0) { this.moveX -= this.width this.translateX(this.moveX) } }, /** * 開始移動(dòng)dom **/ translateX(x) { this.moveX = x < 0 ? 0 : x this.$refs.tabs.children[0].style.transform = `translateX(-${this.moveX}px)` } } } </script> <style lang="scss" scoped> .main-box { height: 500px; width: 500px; padding: 10px 20px 20px 20px; .main-box-tab { position: relative; padding: 10px 20px; overflow: hidden; & > i { position: absolute; cursor: pointer; bottom: 15px; &:nth-child(1) { left: 0; } &:nth-child(2) { right: 0; } } .main-box-tab-content { overflow: hidden; .main-box-tab-roll { transition: transform .5s; display: flex; align-items: center; div { flex-shrink: 0; cursor: pointer; width: 130px; height: 25px; margin: 0 5px; display: flex; align-items: center; justify-content: space-between; span, i { font-size: 12px; } span { margin-left: 10px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } i { margin-right: 10px; } } } } .tab-item { color: #cccccc; background-color: rgba(255, 255, 255, .5); border-radius: 0 1px 0 1px; border: 1px solid #052141; } .tab-item-action { color: #ffffff; background: rgba(0, 180, 255, 0.8); border-radius: 0 1px 0 1px; border: 1px solid #1E2088; } } .main-box-content { height: calc(100% - 70px); padding: 10px; border: 1px saddlebrown solid; background-size: 100% 100%; } } </style>
到此這篇關(guān)于vue實(shí)現(xiàn)tab標(biāo)簽(標(biāo)簽超出自動(dòng)滾動(dòng))的文章就介紹到這了,更多相關(guān)vue tab標(biāo)簽 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue3封裝自動(dòng)滾動(dòng)列表指令(含網(wǎng)頁(yè)縮放滾動(dòng)問(wèn)題)
- vue如何實(shí)現(xiàn)列表自動(dòng)滾動(dòng)、向上滾動(dòng)的效果(vue-seamless-scroll)
- vue-seamless-scroll 實(shí)現(xiàn)簡(jiǎn)單自動(dòng)無(wú)縫滾動(dòng)且添加對(duì)應(yīng)點(diǎn)擊事件的簡(jiǎn)單整理
- vue實(shí)現(xiàn)動(dòng)態(tài)添加數(shù)據(jù)滾動(dòng)條自動(dòng)滾動(dòng)到底部的示例代碼
- vue中使用vue-router切換頁(yè)面時(shí)滾動(dòng)條自動(dòng)滾動(dòng)到頂部的方法
- vue實(shí)現(xiàn)聊天框自動(dòng)滾動(dòng)的示例代碼
相關(guān)文章
vue中接口域名配置為全局變量的實(shí)現(xiàn)方法
今天小編就為大家分享一篇vue中接口域名配置為全局變量的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Vue2.0基于vue-cli+webpack Vuex的用法(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇Vue2.0基于vue-cli+webpack Vuex的用法(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09Vue3中reactive丟失響應(yīng)式問(wèn)題詳解
在vue3中,如果你用reactive聲明了一個(gè)對(duì)象,用另一個(gè)對(duì)象直接給它賦值,那么它就會(huì)失去響應(yīng)式,下面這篇文章主要給大家介紹了關(guān)于Vue3中reactive丟失響應(yīng)式問(wèn)題的相關(guān)資料,需要的朋友可以參考下2023-03-03