element-ui实现导航跟随锚点滚动,为导航menu添加对应的class类

1.首先写一个导航条组件,

           1>组件要求父级传的参数包含一个导航列表:sideMenulist,另包含一个锚点id:selectId

            2>添加点击menu的方法selectMenu,触发父级菜单对应的锚点id:toParentid

<template>
  <div class="sibarmenu">
    <div class="sidebar_title">Dashboard Outline</div>
      <el-menu
        class="el-menu-vertical-demo"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b"
        :default-active="activeIndex"
        @select="selectMenu">
          <div v-for="(item,index) in sideMenulist" :key="item.id">
            <el-menu-item :index="item.id">
              <span slot="title">{{item.firsettitle}}</span>
            </el-menu-item>
            <el-menu-item-group v-if="item.secondtitle.length>0" v-for="(temp,index) in item.secondtitle" :key="temp.id">
              <el-menu-item :index="temp.id">
                <span>{{temp.title}}</span>
              </el-menu-item>
            </el-menu-item-group>
          </div>
      </el-menu>
  </div>
</template>
<script>
  export default{
    props:{
      sideMenulist:{
        type:Array,
        required:true,
      },
      selectId:{
        type:String,
      }
    },
    data() {
      return {
        activeIndex:''
      };
    },
    watch:{
      selectId(){
        this.activeIndex = this.selectId;
      }
    },
    methods: {
      selectMenu(key) {
        this.$emit("toParentid",key);
      },
    },
    mounted(){
      console.log('selectId',this.selectId)
    }
  }
</script>

2.父级页面注入导航条组件

<side-bar @toParentid="showDetails" :sideMenulist="voicesideMenudata" :selectId="selectId"></side-bar>
定义父组件向子组件传递的初始值内容,渲染对应的子组件到父组件中
selectId:null,
voicesideMenudata:[
  {
    firsettitle:'Overall Status',
    id:'Overall Status',
    secondtitle:[]
  },
  {
    firsettitle:'Test Set',
    id:'Test Set',
    secondtitle:[
      {title:'● Short Speech',id:'Test Set Short Speech'},
      {title:'● Long Speech',id:'Test Set Long Speech'},
    ]
  },
  {
    firsettitle:'ASR Engine Test Results',
    id:'ASR Engine Test Results',
    secondtitle:[
      {title:'● Short Speech',id:'ASR Engine Test Results Short Speech'},
      {title:'● Long Speech',id:'ASR Engine Test Results Long Speech'}
    ]
  },
  {
    firsettitle:'Server Test Results',
    id:'Server Test Results',
    secondtitle:[
      {title:'● X86',id:'X86'},
      {title:'● ARM',id:'ARM'}
    ]
  },
  {
    firsettitle:'Others',
    id:'Others',
    secondtitle:[
      {title:'● LeVoice for SIoT–Lecoo插座',id:'LeVoice for SIoT–Lecoo插座'},
      {title:'● LeVoice for SIoT–联想智能空净',id:'LeVoice for SIoT–联想智能空净'},
      {title:'● Smart Headset 语音交互调研',id:'Smart Headset 语音交互调研'},
    ]
  },
],

3.在父组件中添加锚点id和锚点跳转的方法

          1>添加锚点id

             2>添加锚点跳转方法

             //锚点跳转

showDetails(id){

       var el=document.getElementById(id);

       this.$nextTick(function () {

              window.scrollTo({"behavior":"smooth","top":el&&el.offsetTop});

        })

},

添加完这些以后,便可以实现简单的点击导航跳转到对应锚点的功能了

接下来,我们添加滚动页面的时候导航跟随锚点添加对应class类的方法

4.在父级页面中给所有锚点添加一个公用的类

5.在父级页面中监听滚动方法,将可视区内的id传递给子组件的selectId

onScroll(){
        let that = this;
        const navContents = document.querySelectorAll('.acontent')
        // 所有锚点元素的 offsetTop
        const offsetTopArr = []
        navContents.forEach(item => {
          let temp={
            offsetTop:item.offsetTop,
            id:item.id,
          }
          offsetTopArr.push(temp)
        })
        // 获取当前文档流的 scrollTop
        const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
        // 定义当前点亮的导航下标
        let navIndex = ''
        for (let n = 0; n < offsetTopArr.length; n++) {
          // 如果 scrollTop 大于等于第 n 个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
          // 那么此时导航索引就应该是 n 了
          if (scrollTop >= offsetTopArr[n].offsetTop) {
            navIndex = offsetTopArr[n].id;
          }else{

          }
        }
        // 把下标赋值给 vue 的 data
        this.selectId = navIndex;
      },

6.在页面初始化的时候监听滚动条滚动,调用scrollTo方法,在离开页面是销毁监听

mounted(){
  window.addEventListener('scroll', this.onScroll)
},
destroy() {
  // 必须移除监听器,不然当该vue组件被销毁了,监听器还在就会出错
  window.removeEventListener('scroll', this.onScroll)
}

7,赋一个父级页面代码的完整例子,子组件完整代码在文章第一条内容里就有

<template>
  <div class="levoice">
    <div class="content">
      <div>
        <div class="levoice_content" :class="openflag?'levoice_content':'levoice_content_reback'">
          <!--  Overall  -->
          <div>
            <p class="titlebar acontent" id="Overall Status">Overall Status</p>
            <Overall></Overall>
          </div>
          <!--  Testset  -->
          <div>
            <p class="titlebar acontent" id="Test Set">Test Set</p>
            <Testset></Testset>
          </div>
          <!--  ASR Engine Test Result  -->
          <div>
            <!-- <p class="titlebar">ASR Engine Test Result</p> -->
            <p class="titlebar acontent" id="ASR Engine Test Results">ASR Engine Test Results – WER based on Pinyin</p>
            <Asrengine></Asrengine>
          </div>
          <!--  Sever Performance Test Result  -->
          <div>
            <p class="titlebar acontent" id="Server Test Results">Server Performance Test Results</p>
            <Serverperformance v-on:listenToChildEvent="enlargeImg"></Serverperformance>
          </div>
          <!--  Others  -->
          <div>
            <p class="titlebar acontent" id="Others">Others</p>
            <Others v-on:listenToChildEvent="enlargeImg"></Others>
          </div>
        </div>
        <!-- 左侧菜单栏样式  -->
        <div style="border:1px solid #ccc;width:20px;height:100%">
          <div @click="openflag=!openflag" class="sibar_switch" :style="openflag?'left:200px':'left:0'">
            <i :class="openflag?'el-icon-d-arrow-left':'el-icon-d-arrow-right'"></i>
          </div>
        </div>
        <div class="navigation " :class="openflag?'navigation':'navigation_icon'">
          <side-bar @toParentid="showDetails" :sideMenulist="voicesideMenudata" :selectId="selectId"></side-bar>
        </div>
      </div>
    </div>
  </div>
</template>


<script>
  import Overall from '@/components/AI/lenovovoice/overall/mainpage'
  import Testset from '@/components/AI/lenovovoice/testset/mainpage'
  import Asrengine from '@/components/AI/lenovovoice/asrengine/mainpage'
  import Serverperformance from '@/components/AI/lenovovoice/serverperformance/mainpage'
  import Others from '@/components/AI/lenovovoice/others/mainpage'
  import SideBar from '@/components/Common/Sidebar'

  export default {
    data(){
      return{
        openflag:true,
        navTree: [],
        selectId:null,
        voicesideMenudata:[
          {
            firsettitle:'Overall Status',
            id:'Overall Status',
            secondtitle:[]
          },
          {
            firsettitle:'Test Set',
            id:'Test Set',
            secondtitle:[
              {title:'● Short Speech',id:'Test Set Short Speech'},
              {title:'● Long Speech',id:'Test Set Long Speech'},
            ]
          },
          {
            firsettitle:'ASR Engine Test Results',
            id:'ASR Engine Test Results',
            secondtitle:[
              {title:'● Short Speech',id:'ASR Engine Test Results Short Speech'},
              {title:'● Long Speech',id:'ASR Engine Test Results Long Speech'}
            ]
          },
          {
            firsettitle:'Server Test Results',
            id:'Server Test Results',
            secondtitle:[
              {title:'● X86',id:'X86'},
              {title:'● ARM',id:'ARM'}
            ]
          },
          {
            firsettitle:'Others',
            id:'Others',
            secondtitle:[
              {title:'● LeVoice for SIoT–Lecoo插座',id:'LeVoice for SIoT–Lecoo插座'},
              {title:'● LeVoice for SIoT–联想智能空净',id:'LeVoice for SIoT–联想智能空净'},
              {title:'● Smart Headset 语音交互调研',id:'Smart Headset 语音交互调研'},
            ]
          },
        ],
      }
    },
    components:{
      Overall,
      Testset,
      Asrengine,
      Serverperformance,
      Others,
      SideBar
    },
    methods:{
      //点击方法图片
      enlargeImg(msg,title){
        var imgbox = new Image()
        imgbox.src=msg;
        imgbox.alt="nopicure";
        this.$alert("<div class='enlargeImgbox'><img src='"+msg+"'/></div>", title, {
          dangerouslyUseHTMLString: true,
          confirmButtonText: 'Confirm',
          // showConfirmButton:false
        }).catch(()=>{

        });
      },
      //锚点跳转
      showDetails(id){
        var el=document.getElementById(id);
        this.$nextTick(function () {
          window.scrollTo({"behavior":"smooth","top":el&&el.offsetTop});
        })
      },
      onScroll(){
        let that = this;
        const navContents = document.querySelectorAll('.acontent')
        // 所有锚点元素的 offsetTop
        const offsetTopArr = []
        navContents.forEach(item => {
          let temp={
            offsetTop:item.offsetTop,
            id:item.id,
          }
          offsetTopArr.push(temp)
        })
        // 获取当前文档流的 scrollTop
        const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
        // 定义当前点亮的导航下标
        let navIndex = ''
        for (let n = 0; n < offsetTopArr.length; n++) {
          // 如果 scrollTop 大于等于第 n 个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
          // 那么此时导航索引就应该是 n 了
          if (scrollTop >= offsetTopArr[n].offsetTop) {
            navIndex = offsetTopArr[n].id;
          }else{

          }
        }
        // 把下标赋值给 vue 的 data
        this.selectId = navIndex;
      },
    },
    mounted(){
      window.addEventListener('scroll', this.onScroll)
    },
    destroy() {
      // 必须移除监听器,不然当该vue组件被销毁了,监听器还在就会出错
      window.removeEventListener('scroll', this.onScroll)
    },
  }
</script>

 

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HTML中实现锚点定位并具有滚动效果的方法有多种。一种常见的方法是使用CSS的scroll-behavior属性和a标签的href属性。首先,在CSS中设置scroll-behavior属性为smooth,这将使得滚动条在滚动时具有平滑的效果。然后,在a标签中的href属性中设置目标位置的id值,例如#section。当点击该链接时,页面将会平滑滚动到相应的目标位置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [HTML锚点定位+平滑滚动](https://blog.csdn.net/m0_64520392/article/details/128941349)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [微信小程序-scroll-view滚动到指定位置(锚点)](https://download.csdn.net/download/weixin_38601878/16213063)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [vue+导航锚点联动-滚动监听和点击平滑滚动跳转实例](https://download.csdn.net/download/weixin_38665822/13982520)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值