vue点击tab列表滚动对应位置,滚动列表也可切换tab

news/2024/7/24 6:22:21 标签: tab, 锚点

先看看效果:

在这里插入图片描述

<template>
  <div class="custom-demo-view" style="padding: 1rem;">
    <div>
        <el-tabs v-if="reload" v-model="tabIndex" @tab-click="jump">
            <el-tab-pane :label="tabs[0].title" v-if="tabs[0].isShow" name="0"></el-tab-pane>
            <el-tab-pane :label="tabs[1].title" v-if="tabs[1].isShow" name="1"></el-tab-pane>
            <el-tab-pane :label="tabs[2].title" v-if="tabs[2].isShow" name="2"></el-tab-pane>
        </el-tabs>
    </div>
    <div class="scroll-content" @scroll="onScroll" :style="'overflow-x: hidden; overflow-y: auto;height:' + contentStyleObj.height">
        <!-- 用户管理 -->
        <div :ref="tabs[0].refName" class="scroll-item" style="padding-top: 1rem;">
            <div class="line-title">
            <h2>{{tabs[0].title}}</h2>
            </div>
            <div>
                <p style="height:40px" v-for="item in [0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16]" :key="item">待发货符合规范化如故</p>
            </div>
        </div>
        <!-- 配置管理 -->
        <div :ref="tabs[1].refName" class="scroll-item" style="padding-top: 1rem;">
            <div class="line-title">
            <h2>{{tabs[1].title}}</h2>
            </div>
            <div>
                <p style="height:40px" v-for="item in [0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16]" :key="item">新能说出的基本功发到你DNF不得发布</p>
            </div>
        </div>
        <!-- 角色管理 -->
        <div :ref="tabs[2].refName" class="scroll-item" style="padding-top: 1rem;top:5px;">
            <div class="line-title">
            <h2>{{tabs[2].title}}</h2>
            </div>
            <div>
                <p v-for="item in [0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16]" :key="item">新水泥厂剧场版</p>
            </div>
        </div>
    </div>
  </div>
</template>
 
<script>
  export default {
    data() {
      return {
        reload: true,
        tabIndex: '0',
        contentStyleObj: {
          height: '100px'
        },
        tabs: [
          {
            isShow: true,
            title: '用户管理',
            refName: 'setOneRef'
          },
          {
            isShow: true,
            title: '配置管理',
            refName: 'setTwoRef'
          },
          {
            isShow: true,
            title: '角色管理',
            refName: 'setThreeRef'
          }
        ]
      }
    },
    methods: {
      refresh() {
        this.reload = false
        this.$nextTick(() => (this.reload = true))
      },
      // tab click
      jump(index, info) {
        let target = document.querySelector('.scroll-content')
        let scrollItems = document.querySelectorAll('.scroll-item')
        // 判断滚动条是否滚动到底部
        if (target.scrollHeight <= target.scrollTop + target.clientHeight) {
          this.tabIndex = index.index.toString()
        }
        let totalY = scrollItems[index.index].offsetTop - scrollItems[0].offsetTop // 锚点元素距离其offsetParent(这里是body)顶部的距离(待滚动的距离)
        let distance = document.querySelector('.scroll-content').scrollTop // 滚动条距离滚动区域顶部的距离
        // let distance = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset // 滚动条距离滚动区域顶部的距离(滚动区域为窗口)
        // 滚动动画实现, 使用setTimeout的递归实现平滑滚动,将距离细分为50小段,10ms滚动一次
        // 计算每一小段的距离
        let step = totalY / 50
        if (totalY > distance) {
          smoothDown(document.querySelector('.scroll-content'))
        } else {
          let newTotal = distance - totalY
          step = newTotal / 50
          smoothUp(document.querySelector('.scroll-content'))
        }
 
        // 参数element为滚动区域
        function smoothDown(element) {
          if (distance < totalY) {
            distance += step
            element.scrollTop = distance
            setTimeout(smoothDown.bind(this, element), 10)
          } else {
            element.scrollTop = totalY
          }
        }
 
        // 参数element为滚动区域
        function smoothUp(element) {
          if (distance > totalY) {
            distance -= step
            element.scrollTop = distance
            setTimeout(smoothUp.bind(this, element), 10)
          } else {
            element.scrollTop = totalY
          }
        }
      },
      // 滚动条滚动
      onScroll(e) {
        let scrollItems = document.querySelectorAll('.scroll-item')
        for (let i = scrollItems.length - 1; i >= 0; i--) {
          // 判断滚动条滚动距离是否大于当前滚动项可滚动距离
          let judge = e.target.scrollTop >= scrollItems[i].offsetTop - scrollItems[0].offsetTop - 400
          if (judge) {
            this.tabIndex = i.toString()
            break
          }
        }
      },
      getHight() {
        this.contentStyleObj.height = (window.innerHeight - 190) + 'px'
      }
    },
    created() {
      this.getHight()
      window.addEventListener('resize', this.getHight)
    },
    destroyed() {
      window.removeEventListener('resize', this.getHight)
    },
  }
</script>
<style lang="less" scoped>
 
</style>


http://www.niftyadmin.cn/n/1845330.html

相关文章

HTML美化修饰A

<HTML><HEAD><META http-equiv"Content-Type" content"text/html; charsetgb2312"><TITLE>TABLE的美化修饰</TITLE></HEAD> <BODY><TABLE width"957" border"0" background"images…

Json.Net 序列化 IPAddress 或 IPEndPoint

原文: http://stackoverflow.com/questions/18668617/json-net-error-getting-value-from-scopeid-on-system-net-ipaddress class IPAddressConverter : JsonConverter {public override bool CanConvert(Type objectType){return (objectType typeof(IPAddress));}public ov…

react在setState之后数据没变化(setState同步还是异步)

场景是这样的&#xff1a; 我有一个分页列表的场景&#xff0c;目前在点击页码之后&#xff0c;将这个页码setState&#xff0c;然后调用分页接口&#xff0c;如下&#xff1a; // 这是antd的分页上的 onChange事件 const onChange (page, pageSize) > {this.setState({cur…

无法启动WP Emulator

记得以前Vware不能运行设置的东西了吗&#xff1f;http://www.cnblogs.com/dunitian/p/4480750.html 如果不清楚可以参考上面的链接 重启的时候选择第二项 重新打开就ok了~ 补充&#xff1a;

前端上传文件使用FormData给后端传参

这个传参格式已经没什么说的价值了&#xff0c;因为从业的人肯定都用过&#xff0c;但是啊&#xff0c;但是今天有人问我了&#xff0c;所以再说说吧 首先&#xff0c;先把参数转换为new FormData()&#xff1a; let formdata new FormData(); // 如果上传多个文件&#xff…

使用vue init webpack 项目名去构建项目步骤(vue-cli 可视化操作)

1安装npm npm全称为Node Package Manager, 是一个基于Node . js的包管理器&#xff0c;也是整个Node. js社区最流行、支持的第三方模块最多的包管理器。npm -V2由于网络原因安装cnpmnpm install -g cnpm --registryhttps://registry .npm. taobao. org3安装vue-clicnpm install…

react+antd使用Select设置默认选项为后端返回数组的第一项

我知道这个标题看起来就挺傻的&#xff0c;我初入门react&#xff0c;没学过就直接上项目了&#xff0c;有路过大神请指点 问题背景如题&#xff0c;后端返回一个数组&#xff0c;我有一个select框&#xff0c;我要把后端返回数组的第一项设为默认选项。 antd官方文档也看了&am…