滚动导航组件的封装

滚动导航组件的封装


要实现一个如vant库中类似的滚动导航组件

基本监测函数实现实现

可监测传入组件的元素总高度 ,元素垂直方向滚动了的距离 ,元素可视区域高度,是否到达底部

import { onDeactivated, onMounted, onUnmounted, ref } from 'vue';
import { throttle } from 'underscore'
//此函数可传入对应监听的组件,如果没传入,则默认监听window的滚动
export default function useScroll(elRef) {
  let el = window

  const isReachBottom = ref(false)

  const clientHeight = ref(0)
  const scrollTop = ref(0)
  const scrollHeight = ref(0)

  // 防抖/节流
  const scrollListenerHandler = throttle(() => {
    if (el === window) {
      clientHeight.value = document.documentElement.clientHeight
      scrollTop.value = document.documentElement.scrollTop
      scrollHeight.value = document.documentElement.scrollHeight
    } else {
      clientHeight.value = el.clientHeight
      scrollTop.value = el.scrollTop
      scrollHeight.value = el.scrollHeight
    }
//当视口高度+已滚动的高度大于元素高度时,说明已到达底部,可进行相应操作拉取数据
    if (clientHeight.value + scrollTop.value>= scrollHeight.value) {
      console.log("滚动到底部了")
      isReachBottom.value = true
    }
  }, 100)
  
  onMounted(() => {
    if (elRef) el = elRef.value
    el.addEventListener("scroll", scrollListenerHandler)
  })
  
  onUnmounted(() => {
    el.removeEventListener("scroll", scrollListenerHandler)
  })
//导出的这些值可以在其他地方使用
  return { isReachBottom, clientHeight, scrollTop, scrollHeight }
}
获取各个组件的相关内容

我们可以用:ref=‘函数’语法,在组件挂载时执行函数,来获取到页面元素的名字,位置等相关信息

<detail-infos name="描述" :ref="getSectionRef" :top-infos="mainPart.topModule"/>
   // 把相关内容都存储在sectionEls中
  const getSectionRef = (value) => {
  if (!value) return
  const name = value.$el.getAttribute("name")
  sectionEls.value[name] = value.$el
}
    
    
点击跳转

因为我们已经获取到相关dom中的信息,当点击时拿到索引,可以从sectionEls中获取到相关信息,进行跳转,用isclick用来确定是滚动还是点击,防止点击时逐渐变色;

const tabClick = (index) => {
  const key = Object.keys(sectionEls.value)[index]
  const el = sectionEls.value[key]
  let distance = el?.offsetTop
  if (index !== 0) {
    distance = distance - 44
  }
//isclick是用来确定是滚动还是点击,防止点击时逐渐变色
  isClick = true
  currentDistance = distance

  detailRef.value.scrollTo({
    top: distance,
    behavior: "smooth"
  })
}
页面滚动, 滚动时匹配对应的tabControll的index

查找算法,在所有的区域的offsetTops中找第一个offsetTop大于页面滚动距离的前一个组件索引

watch(scrollTop, (newValue) => {
    //点击结束
  if (newValue === currentDistance) {
    isClick = false
  }
  if (isClick) return

  // 1.获取所有的区域的offsetTops
  const els = Object.values(sectionEls.value)
  const values = els.map(el => el?.offsetTop)

  // 2.根据newValue去匹配想要索引
  let index = values.length - 1
  for (let i = 0; i < values.length; i++) {
    if (values[i] > newValue + 44) {
      index = i - 1
      break
    }
  }
  // console.log(index)
  tabControlRef.value?.setCurrentIndex(index)
})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值