qq_875143287 2021-05-22 00:54 采纳率: 60%
浏览 1597
已采纳

前端用vue 实现element ui 的tabs 超长自适应 出现轮播箭头功能

element ui 正常的效果如上图,当tabs 文字超长时 会出现可切换滑动效果和双箭头如下 图

示例链接 https://element.eleme.cn/#/zh-CN/component/tabs

求一份 vue形式的代码  需要实现以下功能  如果不行html 形式文件也可以

1  tabs 总长度自适应当 放不下一行屏幕的时候会出现 红箭头和可以切换的轮播效果

2 动画的效果需要自然,不能出现生硬的卡顿

3 当tabs 总长度小于 一行时不显示箭头 并且 自动flex 居中

  • 写回答

2条回答 默认 最新

  • 斯洛文尼亚旅游 2021-05-23 23:16
    关注

    完工~

     
    <style>#tab1,#tab2{width:400px;margin:20px auto}
    .tab{border:solid 1px #ccc;}
    .tab .container{border-bottom:solid 1px #ccc;background:#eee}
    .tab .wrapper{height:32px;}
    .tab .scroll{padding:0 30px;position:relative}
    .tab .scroll .wrapper{overflow:hidden;position:relative;margin-bottom:-1px}
    .tab .scroll header{width:999999px;position:absolute;transition:all 0.6s cubic-bezier(0.23,1,0.32,1);}
    .tab a.pre,.tab a.next{display:none}
    .tab .scroll a.pre,.tab .scroll a.next{position:absolute;left:8px;top:5px;cursor:pointer;background:#eee;display:block}
    .tab .scroll a.next{left:auto;right:8px}
    .tab .flex{display:flex;justify-content:center;width:auto}
    .tab header .item{padding:5px 15px;float:left;cursor:pointer;position:relative;user-select:none}
    .tab header .item b{display:none;height:0;border-bottom:solid 2px #fff;width:100%;left:0;bottom:-2px;position:absolute}
    .tab header .cur{background:#fff;border-left:solid 1px #ccc;border-right:solid 1px #ccc;color:#007bffb5;border-top-left-radius:5px;border-top-right-radius:5px;}
    .tab header .cur b{display:block}
    .tab .clear{clear:both}
    .tab .tabody{padding:10px}
    </style>
    <div class="tab" id="tab1">
        <div v-bind:class="{scroll:scroll,container:1}">
            <div class="wrapper">
                <header v-bind:class="{flex:flex}" v-bind:style="{left:left+'px'}">
                    <div v-for="(item,index) in tabs" v-bind:class="{item:1,cur:index==curIndex}" v-on:click="setCur(index,$event)">{{item}}<b></b></div>
                    <div class="clear"></div>
                </header>
            </div>
            <a class="pre" v-on:click="preNext(1)">&lt;</a>
            <a class="next" v-on:click="preNext(-1)">&gt;</a>
        </div>
        <div class="tabody">
            <div v-for="(item,index) in tabs" v-bind:style="{display:index==curIndex?'block':'none'}">{{item}}</div>
        </div>
    </div>
    <div class="tab" id="tab2">
        <div v-bind:class="{scroll:scroll,container:1}">
            <div class="wrapper">
                <header v-bind:class="{flex:flex}" v-bind:style="{left:left+'px'}">
                    <div v-for="(item,index) in tabs" v-bind:class="{item:1,cur:index==curIndex}" v-on:click="setCur(index,$event)">{{item}}<b></b></div>
                    <div class="clear"></div>
                </header>
            </div>
            <a class="pre" v-on:click="preNext(1)">&lt;</a>
            <a class="next" v-on:click="preNext(-1)">&gt;</a>
        </div>
        <div class="tabody">
            <div v-for="(item,index) in tabs" v-bind:style="{display:index==curIndex?'block':'none'}">{{item}}</div>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#tab1',
            data: {
                tabs: ['选项卡1', '选项卡2', '选项卡3', '选项卡4', '选项卡5', '选项卡6', '选项卡7', '选项卡8', '选项卡9'],
                curIndex: 0,
                flex: 0,
                scroll: 0,
                left:0
            },
            methods: {
                setCur(index,e) {
                    this.curIndex = index;
                    if (this.scroll) {
                        var el = e.target, left = parseInt(el.getAttribute('left'));
                        this.isInView(left, left+ el.offsetWidth)
                    }
                },
                preNext(dir) {
                    var left = this.left + dir * this.stepWidth;
                    if (left < this.maxLeft) left = this.maxLeft;
                    else if (left>0)left=0
                    this.left = left;
                },
                isInView(left,right) {
                    var left1 = -1 * this.left, right1 = -1 * (this.left - this.stepWidth);
                    if (left < left1 || left > right1 || right < left1 || right > right1) {
                        if (left < left1) this.left = -left + 2;
                        else this.left = -right + this.stepWidth;
                    }
                }
            },
            mounted() {
                var wrapper = this.$el.querySelector('.wrapper'); 
                if (wrapper.scrollHeight > wrapper.offsetHeight + 2) {
                    var items = wrapper.querySelectorAll('.item');
                    var w = 0;
                    for (var item of items) { item.setAttribute('left', w); w += item.offsetWidth;}
                    this.header=wrapper.querySelector('header').style.width = w + 'px';
                    this.scroll = 1;
                    this.stepWidth = wrapper.clientWidth - 60;
                    this.maxLeft = this.stepWidth - w;
                }
                else this.flex = 1;
            }
        });
        new Vue({
            el: '#tab2',
            data: {
                tabs: ['选项卡1', '选项卡2', '选项卡3'],
                curIndex: 1,
                flex: 0,
                scroll: 0,
                left: 0
            },
            methods: {
                setCur(index, e) {
                    this.curIndex = index;
                    if (this.scroll) {
                        var el = e.target, left = parseInt(el.getAttribute('left'));
                        this.isInView(left, left + el.offsetWidth)
                    }
                },
                preNext(dir) {
                    var left = this.left + dir * this.stepWidth;
                    if (left < this.maxLeft) left = this.maxLeft;
                    else if (left > 0) left = 0
                    this.left = left;
                },
                isInView(left, right) {
                    var left1 = -1 * this.left, right1 = -1 * (this.left - this.stepWidth);
                    if (left < left1 || left > right1 || right < left1 || right > right1) {
                        if (left < left1) this.left = -left + 2;
                        else this.left = -right + this.stepWidth;
                    }
                }
            },
            mounted() {
                var wrapper = this.$el.querySelector('.wrapper');
                if (wrapper.scrollHeight > wrapper.offsetHeight + 2) {
                    var items = wrapper.querySelectorAll('.item');
                    var w = 0;
                    for (var item of items) { item.setAttribute('left', w); w += item.offsetWidth; }
                    this.header = wrapper.querySelector('header').style.width = w + 'px';
                    this.scroll = 1;
                    this.stepWidth = wrapper.clientWidth - 60;
                    this.maxLeft = this.stepWidth - w;
                }
                else this.flex = 1;
            }
        });
    </script>
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 关于#vscode#的问题:ESP32开发板对接MQTT实现小灯泡的开关
  • ¥15 TMC2209串口模式下读取不到寄存器的值串口助手蓝色字体是发过去的消息,绿色字体是收到的消息,第二行发送读取寄存器的指令但是没有读取到寄存器的值串口助手如下图:接线如下图,如何解决?
  • ¥15 高通安卓11提取完整线刷包软件,或者优博讯dt50顺丰刷机包
  • ¥20 C,有个译码器,换了信道就跑不出原来数据
  • ¥15 MIMIC数据库安装问题
  • ¥60 基于JTag协议开发Fpga下载器上位机,哪位大🐂有偿指导?
  • ¥20 全书网Java爬取数据
  • ¥15 怎么获取红包封面的原始链接,并且获取红包封面序列号
  • ¥100 微信小程序跑脚本授权的问题
  • ¥100 房产抖音小程序苹果搜不到安卓可以付费悬赏