vue可滑動(dòng)的tab組件使用詳解
本文實(shí)例為大家分享了vue可滑動(dòng)tab組件使用的具體代碼,供大家參考,具體內(nèi)容如下
需求:
1. 每個(gè)tab-item的間距是相同的,可定制
2. 每一個(gè)tab-item的寬度是隨著文字的增多而寬度增大
3. 當(dāng)tab-item小于等于4個(gè)時(shí),tab-item填滿當(dāng)前屏幕,平分剩余空間;當(dāng)tab-item超過(guò)4個(gè)時(shí),tab可滑動(dòng)選擇
4. 點(diǎn)擊tab-item時(shí),底部橫線居中顯示,跟隨在點(diǎn)擊的tab-item底部
5. 從上一個(gè)頁(yè)面點(diǎn)擊一級(jí)分類,進(jìn)入此頁(yè)面,顯示上一頁(yè)面點(diǎn)擊的一級(jí)分類名稱,居中顯示,樣式高亮
先展示效果截圖
前期知識(shí)點(diǎn)
1)offsetLeft:子元素相對(duì)于父元素最左上角側(cè)的橫向偏離位置
2)offsetWidth: 元素的寬度
3)scrollLeft: 滑動(dòng)到對(duì)應(yīng)的x坐標(biāo)
4)定位元素style.left的運(yùn)用
5)vux組件之滑動(dòng)tab的運(yùn)用 (需要用到組件自帶的onItemClick()方法,通過(guò)dom,可以起到點(diǎn)擊該tab-item的作用)
難點(diǎn)
1)使用vux的可滑動(dòng)的tab,修改組件css,如何令到每一個(gè)tab的間距為響應(yīng)式的。
原本vux的可滑動(dòng)的tab是根據(jù)scrollWidth的長(zhǎng)度來(lái)自動(dòng)計(jì)算每一個(gè)tab-item的寬度的,因?yàn)榘@tab-item的tabBox這個(gè)div使用的是flex布局,而tab-item是它的子元素,它會(huì)自動(dòng)沾滿tabBox。如果文字超出了tab-item的寬度,文字就會(huì)被隱藏。
可以通過(guò)修改vux-tab-item這個(gè)樣式來(lái)自定義樣式,把子元素的彈性屬性去除,并且設(shè)置他的padding,這樣可以呈現(xiàn)出文字能顯示全,并且每個(gè)tab-item間距相同的效果,css如下:
/*改變?cè)瓉?lái)tabBox的flex布局*/ .mpm-container .vux-tab .vux-tab-item { ? display: inline-block; ? width: auto; ? height: 100%; ? padding: 0 10px; ? flex: none; ? background: transparent; ? overflow: hidden; }
2)這個(gè)組件最核心之一的就是底部bar的精準(zhǔn)定位跟隨
因?yàn)樯厦娴?)改變了布局,所以導(dǎo)致底部bar跟隨不準(zhǔn)確的情況,我們可以定制bar。在vux里面,bar是一個(gè)div,它有滑動(dòng)的動(dòng)畫,我的做法是這樣的,首先通過(guò)right讓它置于tab的最左側(cè),然后通過(guò)按鈕點(diǎn)擊事件獲得相對(duì)應(yīng)的tab-item元素的下標(biāo),然后使用for循環(huán)從第一tab-item開(kāi)始尋找,如果不為改元素,則把它的元素寬度進(jìn)行累加,直到找到該需激活的tab-item,然后通過(guò)數(shù)學(xué)計(jì)算可把bar定位在該元素的底部并且居中,代碼如下:
onItemClick(keyword, index) { ? ? ? let barLeft = 0; ? ? ? document.getElementsByClassName('vux-tab-ink-bar')[0].style.right = '100%'; ? ? ? for (let i = 0; i < this.list.length; i++) { ? ? ? ? if (document.getElementsByClassName('vux-tab-item')[i].innerText === keyword) { ? ? ? ? ? barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth / 2; ? ? ? ? ? //為什么是15?因?yàn)榈撞縝ar長(zhǎng)度為30px,這樣做可以讓bar的中心對(duì)齊tab-item的中心 ? ? ? ? ? barLeft -= 15; ? ? ? ? ? break; ? ? ? ? } ? ? ? ? barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth; ? ? ? } ? ? ? document.getElementsByClassName('vux-tab-ink-bar')[0].style.left = (barLeft + 'px'); ? ? },
3)從前一個(gè)頁(yè)面點(diǎn)擊一級(jí)分類進(jìn)入商品列表頁(yè),自動(dòng)選中并在屏幕居中顯示被選中的tab-item
當(dāng)超出手機(jī)的可視寬度時(shí),獲取當(dāng)前屏幕寬度,然后評(píng)分長(zhǎng)度,計(jì)算之后,平均分給tab-item,因?yàn)槊恳粋€(gè)tab-item自己的樣式中有設(shè)置的padding屬性,所以間距相同,不需要額外為間距分配空間。
否則則不需要分配寬度,因?yàn)槭莊lex布局的子元素,每一個(gè)tab-item會(huì)根據(jù)自己的文字得到自己的寬度。
附完整代碼:
<template> ? <div class="mpm-container"> ? ? <div style="width: 100%;overflow:scroll; -webkit-overflow-scrolling:touch;"> ? ? ? <tab ref="tabBox" bar-active-color="#149c81" active-color="#149c81" :line-width="4" :custom-bar-width="getBarWidth" v-model="tabD" :style="{width: tabWidth + 'px'}"> ? ? ? ? <tab-item v-for="(item,index) in list" :key="index" @on-item-click="onItemClick(item, index)">{{item}} ? ? ? ? </tab-item> ? ? ? </tab> ? ? </div> ? </div> </template> ? <script> import { ? Tab, TabItem } from 'vux'; ? export default { ? data() { ? ? return { ? ? ? list: ['打印機(jī)', '訂書機(jī)11111111', '訂書機(jī)5', '打印機(jī)333333', '復(fù)讀機(jī)333333',], ? ? ? tabD: 0, ? ? ? // tab標(biāo)簽div長(zhǎng)度 ? ? ? tabWidth: document.body.clientWidth, ? ? } ? }, ? computed: {}, ? components: { ? ? Tab, TabItem ? }, ? mounted() { ? ? setTimeout(() => { ? ? ? this.$refs.tabBox.$children[0].onItemClick(); ? ? }, 200) ? ? this.setTabWidth(); ? }, ? methods: { ? ? setTabWidth() { ? ? ? // 頁(yè)面完成刷新之后 ? ? ? this.$nextTick(() => { ? ? ? ? var realW = 0, offW = 0; ? ? ? ? // realW為每一個(gè)tab-item的長(zhǎng)度總和,因?yàn)閠ab-item的父級(jí)為flex布局,而tab-item的flex: none,所以初始化的時(shí)候,tab-item會(huì)根據(jù)自己的字體長(zhǎng)度,自動(dòng)擴(kuò)張寬度。 ? ? ? ? for (let i = 0; i < this.$refs.tabBox.$children.length; i++) { ? ? ? ? ? realW += this.$refs.tabBox.$children[i].$el.offsetWidth; ? ? ? ? } ? ? ? ? // 同樣是計(jì)算初始化的時(shí)候,每一個(gè)tab-item的總寬度,但當(dāng)tab-item總長(zhǎng)度大于tab的總長(zhǎng)度時(shí),立馬退出程序 ? ? ? ? for (let i = 0; i < this.$refs.tabBox.$children.length; i++) { ? ? ? ? ? offW += this.$refs.tabBox.$children[i].$el.offsetWidth; ? ? ? ? ? if (offW > (document.body.clientWidth)) break ? ? ? ? } ? ? ? ? // 假如tab-item的總寬度小于顯示tabwidth,則評(píng)分tab的剩余空間,加到每一個(gè)tab-item中 ? ? ? ? if (offW < (document.body.clientWidth)) { ? ? ? ? ? var offD = (document.body.clientWidth) - offW; ? ? ? ? ? for (let i = 0; i < this.$refs.tabBox.$children.length; i++) { ? ? ? ? ? ? this.$refs.tabBox.$children[i].$el.style.width = this.$refs.tabBox.$children[i].$el.clientWidth + offD / this.$refs.tabBox.$children.length + 'px'; ? ? ? ? ? } ? ? ? ? } else { ? ? ? ? ? this.tabWidth = realW; ? ? ? ? } ? ? ? }) ? ? }, ? ? getBarWidth() { ? ? ? // 函數(shù)控制tab-bar的寬度,如果tab標(biāo)簽頁(yè)數(shù)量為1,則隱藏tab-bar ? ? ? if (this.list && this.list.length === 1) { ? ? ? ? return '0px'; ? ? ? } ? ? ? return '30px'; ? ? }, ? ? onItemClick(keyword, index) { ? ? ? let barLeft = 0; ? ? ? document.getElementsByClassName('vux-tab-ink-bar')[0].style.right = '100%'; ? ? ? for (let i = 0; i < this.list.length; i++) { ? ? ? ? if (document.getElementsByClassName('vux-tab-item')[i].innerText === keyword) { ? ? ? ? ? barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth / 2; ? ? ? ? ? //為什么是15?因?yàn)榈撞縝ar長(zhǎng)度為30px,這樣做可以讓bar的中心對(duì)齊tab-item的中心 ? ? ? ? ? barLeft -= 15; ? ? ? ? ? break; ? ? ? ? } ? ? ? ? barLeft += document.getElementsByClassName('vux-tab-item')[i].offsetWidth; ? ? ? } ? ? ? document.getElementsByClassName('vux-tab-ink-bar')[0].style.left = (barLeft + 'px'); ? ? }, ? ? } } ? </script> ? <style scoped lang="less"> /*改變?cè)瓉?lái)tabBox的flex布局*/ .mpm-container .vux-tab .vux-tab-item { ? display: inline-block; ? width: auto; ? height: 100%; ? padding: 0 10px; ? flex: none; ? background: transparent; ? overflow: hidden; } </style>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue如何實(shí)現(xiàn)表單多選并且獲取其中的值
這篇文章主要介紹了vue如何實(shí)現(xiàn)表單多選并且獲取其中的值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07vue項(xiàng)目如何實(shí)現(xiàn)Echarts在label中獲取點(diǎn)擊事件
這篇文章主要介紹了vue項(xiàng)目如何實(shí)現(xiàn)Echarts在label中獲取點(diǎn)擊事件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10前端登錄退出處理Token問(wèn)題(獲取、緩存、失效處理)及代碼實(shí)現(xiàn)方法
token是一個(gè)用戶信息的表示,在登錄中將會(huì)從后端拿到token,然后用戶才可以進(jìn)行往后的一系列操作,這篇文章主要給大家介紹了關(guān)于前端登錄退出處理Token問(wèn)題(獲取、緩存、失效處理)及代碼實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2024-01-01使用Vue開(kāi)發(fā)自己的Chrome擴(kuò)展程序過(guò)程詳解
這篇文章主要介紹了使用Vue開(kāi)發(fā)自己的Chrome擴(kuò)展程序過(guò)程詳解,瀏覽器擴(kuò)展程序是可以修改和增強(qiáng) Web 瀏覽器功能的小程序。它們可用于各種任務(wù),例如阻止廣告,管理密碼,組織標(biāo)簽,改變網(wǎng)頁(yè)的外觀和行為等等。,需要的朋友可以參考下2019-06-06利用vue-router實(shí)現(xiàn)二級(jí)菜單內(nèi)容轉(zhuǎn)換
這篇文章主要介紹了如何利用vue-router實(shí)現(xiàn)二級(jí)菜單內(nèi)容轉(zhuǎn)換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11通過(guò)Element ui往頁(yè)面上加一個(gè)分頁(yè)導(dǎo)航條的方法
這篇文章主要介紹了通過(guò)Element ui往頁(yè)面上加一個(gè)分頁(yè)導(dǎo)航條的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05vue使用formData時(shí)候傳遞參數(shù)是個(gè)空值的情況處理
這篇文章主要介紹了vue使用formData時(shí)候傳遞參數(shù)是個(gè)空值的情況處理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05