vue实现侧边定位栏

本文实例为大家分享了vue实现侧边定位栏的具体代码,供大家参考,具体内容如下

实现思路:

1.通过点击侧边栏,定位到响应的内容
2.滑动滑动栏,侧边栏同步高亮对应的item

效果图如下:

1. 通过点击侧边栏,定位到响应的内容

如果是用html的话我们可以用 锚点 的办法进行定位;
在vue中,我们可以通过获取组件的高度,将滑动栏定位到对应的位置

在进入主题之前我们需要先了解3个关于获取高度的属性

1.scrollTop 滑动栏中的滑块离视区最顶部的距离

document.documentElement.scrollTop || document.body.scrollTop

2.clientHeight 视区的高度

document.documentElement.clientHeight || document.body.clientHeight

3.scrollHeight 滑动栏里面的滑动块的高度

document.documentElement.scrollHeight || document.body.scrollHeight

vue中我们可以通过this.$refs.xxx.$el.offsetTop获取组件距离页面最顶部的距离,通过赋值给document.documentElement.scrollTop选中组件距离页面最顶部的高度,控制滑动框滑到页面对应位置。相关代码如下:

页面代码

// 页面组件代码 <div>     <btl-header />     <div class="reports">       <side-bar v-bind="sideBarData" />       <div class="main">         <live-overview-part           ref="liveOverview"           :shopNameOptions="allShopName"           :dateSelectorData="dateType_0" />         <procurenment-alert           ref="procurenmentAlert"           :carBrandOptions="carBrandOptions"           :shopNameOptions="allShopName"           :dateSelectorData="dateType_2" />         <sales-overview           ref="salesOverview"           :shopNameOptions="allShopName"           :dateSelectorData1="pardsType_0"           :dateSelectorData2="dateType_1" />         <inquiry-data           ref="inquiryData"           :shopNameOptions="allShopName"           :dateSelectorData="dateType_2" />         <transaction-data           ref="transactionData"           :carBrandOptions="carBrandOptions"           :shopNameOptions="allShopName"           :qualityOptions="qualityOptions"           :colorSeries="colorSeries"           :dateSelectorData="dateType_2" />       </div>     </div> //  获取组件距离页面顶部高度 !!!  <script> mounted() {     // !!注意,需要页面渲染完才能获取各个盒子的高度     this.sideBarData.offsetTopliveOverview = this.$refs.liveOverview.$el.offsetTop;     this.sideBarData.offsetTopprocurenmentAlert = this.$refs.procurenmentAlert.$el.offsetTop;     this.sideBarData.offsetTopsalesOverview = this.$refs.salesOverview.$el.offsetTop;     this.sideBarData.offsetTopinquiryData = this.$refs.inquiryData.$el.offsetTop;     this.sideBarData.offsetToptransactionData = this.$refs.transactionData.$el.offsetTop;    },   </script>

侧边栏实现代码

// 侧边栏代码 <template>   <hn-card class="sidebar">     <ul class="nav-tabs">       <li         class="activeTip"         ref="activeTip"></li>       <li         @click="clickanchor('liveOverview',0)"         class="item"         :class="active==='liveOverview'?'active':'noActive'">实时总览</li>       <li         class="item"         :class="active==='procurenmentAlert'?'active':'noActive'"         @click="clickanchor('procurenmentAlert',1)">采购预警</li>       <li         class="item"         :class="active==='salesOverview'?'active':'noActive'"         @click="clickanchor('salesOverview',2)">销售概览</li>       <li         class="item"         :class="active==='inquiryData'?'active':'noActive'"         @click="clickanchor('inquiryData',3)">询价数据</li>       <li         class="item"         :class="active==='transactionData'?'active':'noActive'"         @click="clickanchor('transactionData',4)">交易数据</li>       <li         class="item"         :class="active==='top'?'active':'noActive'"         @click="clickanchor('top')">返回顶部</li>     </ul>   </hn-card> </template> // 侧边栏js <script> methods: { // 点击侧边栏item时触发 // 通过document.documentElement.scrollTop控制滑动栏位置     clickanchor(itemName, i) {       if (itemName === 'top') {         document.documentElement.scrollTop = 0; // 滑动栏位置         this.active = itemName;         this.$refs.activeTip.style.transform = `translateY(${196}px)`;         return;       }       this.$refs.activeTip.style.transform = `translateY(${i * 39}px)`;       document.documentElement.scrollTop = this[`offsetTop${itemName}`];       this.active = itemName;     }, </script>

2. 滑动滑动栏,侧边栏同步高亮对应的item

通过监听滑动栏滑动,获取滑动块距离页面顶部的高度,和组件距离页面顶部的高度进行对比,反向设置滑动栏的高亮位置;

// 监听滑动栏滚动,通过监听滚动到的位置,到     scrollChange() {       const scrollTop = document.documentElement.scrollTop || document.body.scrollTop || 0;       const windowHeight = document.documentElement.clientHeight || document.body.clientHeight || 0;       const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight || 0;       const allContentOffsettop = [         'offsetTopliveOverview',         'offsetTopprocurenmentAlert',         'offsetTopsalesOverview',         'offsetTopinquiryData',         'offsetToptransactionData'];       if (scrollTop === 0) {         if (this.active !== 'top') {           this.active = 'top';           this.$refs.activeTip.style.transform = `translateY(${196}px)`;         }       } else if (scrollTop + windowHeight > scrollHeight || scrollTop + windowHeight === scrollHeight) {         if (this.active !== 'transactionData') {           this.active = 'transactionData';           this.$refs.activeTip.style.transform = `translateY(${157}px)`;         }       } else {         for (let i = 0; i < allContentOffsettop.length; i++) {           if (this[allContentOffsettop[i]] - 1 > scrollTop) {             const contentName = allContentOffsettop[i - 1].replace('offsetTop', '');             if (this.active !== contentName) {               this.active = contentName;               this.$refs.activeTip.style.transform = `translateY(${(i - 1) * 39}px)`;             }             break;           }         }       }     },   }, };

推荐阅读