最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue實(shí)現(xiàn)tab標(biāo)簽(標(biāo)簽超出自動(dòng)滾動(dòng))

 更新時(shí)間:2021年05月25日 11:26:53   作者:卑鄙的你  
當(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)簽,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

當(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í)可見的元素個(gè)數(shù)) * 單個(gè)tab標(biāo)簽元素長(zhǎng)度 - 被遮擋tab元素的可見部分的寬度
                    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元素的可見部分的寬度 = 可見區(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)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue中input被賦值后,無(wú)法再修改編輯的問(wèn)題及解決

    Vue中input被賦值后,無(wú)法再修改編輯的問(wèn)題及解決

    這篇文章主要介紹了Vue中input被賦值后,無(wú)法再修改編輯的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue引用js文件的多種方式(推薦)

    vue引用js文件的多種方式(推薦)

    這篇文章主要介紹了vue引用js文件的多種方式,本文大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05
  • vue?elementUI?處理文件批量上傳方式

    vue?elementUI?處理文件批量上傳方式

    這篇文章主要介紹了vue?elementUI?處理文件批量上傳方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • 解決vue終端報(bào)錯(cuò):不是內(nèi)部或外部命令

    解決vue終端報(bào)錯(cuò):不是內(nèi)部或外部命令

    最近學(xué)習(xí)一下前端框架Vue,整體上感覺還是比較有意思的,但是在安裝vue-cli腳手架的時(shí)候,出現(xiàn)了一些問(wèn)題,解決問(wèn)題也花費(fèi)了不少時(shí)間,下面這篇文章主要給大家介紹了關(guān)于解決vue終端報(bào)錯(cuò):不是內(nèi)部或外部命令的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Vue中nvm-windows的安裝與使用教程(親測(cè))

    Vue中nvm-windows的安裝與使用教程(親測(cè))

    nvm全英文也叫node.js version management,是一個(gè)nodejs的版本管理工具,這篇文章主要介紹了Vue中nvm-windows的安裝與使用,需要的朋友可以參考下
    2023-02-02
  • vue項(xiàng)目如何解決數(shù)字計(jì)算精度問(wèn)題

    vue項(xiàng)目如何解決數(shù)字計(jì)算精度問(wèn)題

    這篇文章主要介紹了vue項(xiàng)目如何解決數(shù)字計(jì)算精度問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Vue插件寫、用詳解(附demo)

    Vue插件寫、用詳解(附demo)

    本篇文章主要介紹了Vue插件寫、用詳解(附demo),插件就是指對(duì)Vue的功能的增強(qiáng)或補(bǔ)充。有興趣的可以了解一下。
    2017-03-03
  • vue實(shí)現(xiàn)圖片切換效果

    vue實(shí)現(xiàn)圖片切換效果

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)圖片切換效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 詳解vue中在父組件點(diǎn)擊按鈕觸發(fā)子組件的事件

    詳解vue中在父組件點(diǎn)擊按鈕觸發(fā)子組件的事件

    這篇文章主要介紹了詳解vue中在父組件點(diǎn)擊按鈕觸發(fā)子組件的事件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Vue2和Vue3中如何使用WebSocker封裝詳解

    Vue2和Vue3中如何使用WebSocker封裝詳解

    如果項(xiàng)目中多個(gè)組件都使用到WebSocket請(qǐng)求,那么我們需要對(duì)WebSocket進(jìn)行封裝,方便我們使用,下面這篇文章主要給大家介紹了關(guān)于Vue2和Vue3中如何使用WebSocker封裝的相關(guān)資料,需要的朋友可以參考下
    2024-07-07

最新評(píng)論

宜川县| 汪清县| 集贤县| 南丰县| 黔西县| 永丰县| 上杭县| 湘西| 凤冈县| 昌宁县| 九台市| 察哈| 小金县| 新巴尔虎右旗| 阳新县| 延长县| 独山县| 交口县| 耒阳市| 丘北县| 吉木萨尔县| 孟村| 屏东县| 周口市| 五家渠市| 南昌市| 读书| 海阳市| 齐齐哈尔市| 雅安市| 荣昌县| 黎平县| 钦州市| 泗洪县| 金平| 元谋县| 肥西县| 白朗县| 聂拉木县| 湖口县| 子洲县|