返回顶部
首页 > 资讯 > 前端开发 > JavaScript >vue实现tab标签(标签超出自动滚动)
  • 799
分享到

vue实现tab标签(标签超出自动滚动)

2024-04-02 19:04:59 799人浏览 薄情痞子
摘要

当创建的tab标签超出页面可视区域时自动滚动一个tab标签距离,并可手动点击滚动tab标签,实现效果请看GIF图 效果预览GIF图 <template> &

当创建的tab标签超出页面可视区域时自动滚动一个tab标签距离,并可手动点击滚动tab标签,实现效果请看GIF图

效果预览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
                // 如有重复数据退出后续函数执行
                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(() => {
                  // (总共有多少个tabs - 未偏移时可见的元素个数) * 单个tab标签元素长度 - 被遮挡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))
                // 元素实际宽度 = 元素的宽度 + 外边距
                this.width = marginLeft + marginRight + tabs.children[0].children[0].offsetWidth

                
                // // 可视区域能放入多少个元素 = 可视区域的宽度 / 子元素实际宽度
                // let num = tabs.offsetWidth / this.width

                // // 被遮挡tab元素的可见部分的宽度 = 可见区域的宽度 - (子元素实际宽度 * num转为整数)
                // this.unoccupied = tabs.offsetWidth - (this.width * parseInt(num))

                // 最终精简为取余(得数跟上面的计算是一样的)
                this.unoccupied = tabs.offsetWidth % this.width
                // 转为整数
                this.tabsCount = parseInt(tabs.offsetWidth / this.width)
            })
        },
        methods: {
            add() {
                this.count++
                this.actionName = `test${this.count}`
            },

            
            clickTab(name) {
                if (this.actionName !== name) {
                    this.actionName = name
                }
            },

            
            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获取不准确
                // 使用this.width * this.tabs.length计算出总长度
                let totalWidth = this.width * this.tabs.length

                this.$nextTick(() => {
                    let dom = this.$refs.tabs
                    // 可视区域 < 滚动区域(滚动区域大于可视区域才可以移动)
                    // 移动距离 + 可视区域 = 滚动区域的宽度(上一次的宽度,当点击时才是实际宽度)< 滚动区域
                    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)
                }
            },

            
            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>

到此这篇关于Vue实现tab标签(标签超出自动滚动)的文章就介绍到这了,更多相关vue tab标签 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: vue实现tab标签(标签超出自动滚动)

本文链接: https://lsjlt.com/news/126775.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • vue实现tab标签(标签超出自动滚动)
    当创建的tab标签超出页面可视区域时自动滚动一个tab标签距离,并可手动点击滚动tab标签,实现效果请看GIF图 效果预览GIF图 <template> &...
    99+
    2024-04-02
  • vue-router如何实现tab标签页
    这篇文章主要介绍了vue-router如何实现tab标签页,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。vue-router 是 Vue.j...
    99+
    2024-04-02
  • 使用vue怎么实现tab标签
    使用vue怎么实现tab标签?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。<template>    <div&n...
    99+
    2023-06-15
  • Vue如何替代marquee标签超出宽度文字横向滚动效果
    这篇文章主要介绍了Vue如何替代marquee标签超出宽度文字横向滚动效果,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、npm 安装如果...
    99+
    2024-04-02
  • Android实现滑动标签页
    本文实例为大家分享了Android实现滑动标签页的具体代码,供大家参考,具体内容如下 TabLayoutActivity.java package cn.edu.zufe.ap...
    99+
    2024-04-02
  • Vue中video标签如何实现不静音自动播放
    由于浏览器厂商为了提高用户体验禁止video标签可以有声的自动播放,也就是说如果想让video标签能够自动播放必须给video标签添加muted属性。 但是在开发的过程中我们需要用视...
    99+
    2023-01-31
    vue中使用video标签视频播放 vue video vue视频播放组件
  • JavaScript实现内容滚动与导航标签互动关联方案
    目录一、需求场景描述1.先看演示效果2.需求分解二、关键技术点提前知技术点1:Element.scrollIntoView()技术点2:Element.getBoundingClie...
    99+
    2024-04-02
  • Android自定义ViewGroup实现标签浮动效果
    前面在学习鸿洋大神的一些自定义的View文章,看到了自定义ViewGroup实现浮动标签,初步看了下他的思路以及结合自己的思路完成了自己的浮动标签的自定义ViewGroup。目...
    99+
    2022-06-06
    动效 标签 Android
  • html中如何实现p标签自动换行
    这篇文章主要介绍html中如何实现p标签自动换行,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 着实p标签为html段落标签,默许是自动换行的,无庸配置任何css花式属性,p标签会...
    99+
    2024-04-02
  • Input标签自动校验功能去除实现
    目录自动校验解决方法解决思路多种解决方法1、ConfigProvider2、修改defaultProps3、拦截React.createElement4、全局监听input事件5、M...
    99+
    2024-04-02
  • vue如何动态引入img标签
    在vue中动态引入img标签的方法:1.新建vue.js项目;2.添加img标签并提供地址;3.配置config.js文件;4.在项目中应用配置文件;具体步骤如下:首先,在vue-cli中创建一个vue.js项目;vue create pr...
    99+
    2024-04-02
  • 如何让pre标签自动换行
    这篇文章给大家分享的是有关如何让pre标签自动换行的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。pre 元素可定义预格式化的文本。被包围在 pre 元素中的文本通常会保留空格和换...
    99+
    2024-04-02
  • CSS怎么实现Tab切换标签效果
    这篇文章主要讲解了“CSS怎么实现Tab切换标签效果”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“CSS怎么实现Tab切换标签效果”吧!本文实例讲述了纯CS...
    99+
    2024-04-02
  • vue-meta实现router动态设置meta标签的方法
    目录一. meta标签提供关于HTML文档的元数据(元数据指用来描述数据的数据)。二.meta标签的特点三.通过引入vue-meta模块四.vue路由中动态设置title与meta一...
    99+
    2022-11-21
    vue meta标签 vue router meta标签
  • jQuery实现动态添加标签事件
    本文实例为大家分享了jQuery实现动态添加标签事件的具体代码,供大家参考,具体内容如下 代码: <body> <table id="tableID"...
    99+
    2024-04-02
  • DEDECMS 扩展标签和dede自定义标签实现方法
    我们需要知道下扩展标签的存放目录及文件名构成,首先,扩展的标签都是存放在/include/taglib这个目录,名称都是以“标签名.lib.php”格式,例如{dede:channel/}标签对应...
    99+
    2022-06-12
    DEDECMS 扩展标签 自定义标签
  • HTML滚动标签marquee的属性有什么用
    HTML滚动标签marquee的属性可以用于控制滚动文本或图像的行为和样式。以下是marquee标签常用的属性:1. directi...
    99+
    2023-10-18
    HTML
  • HTML 框架标签:创建可滚动的区域
    创建可滚动的区域是 Web 开发中常见的需求,它允许用户在页面内容超出会话窗口大小时对其进行浏览。HTML 中的 <iframe> 元素提供了一种便捷的方法来实现此功能。 <iframe> 元素 <ifram...
    99+
    2024-03-13
    框架标签
  • Input标签自动校验功能去除怎么实现
    今天小编给大家分享一下Input标签自动校验功能去除怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。自动校验注:以下输...
    99+
    2023-07-02
  • vue实现鼠标滑动展示tab栏切换
    本文实例为大家分享了vue实现鼠标滑动展示tab栏切换的具体代码,供大家参考,具体内容如下 动画效果: 代码如下: <template>   <div id="h...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作