SideBar 侧边导航与内容区域交互重写【Ant Design Mobile】

需求:SideBar 侧边导航与内容区域交互

  1. 点击侧边栏某一项时,相对应内容区域滚动到视口顶部
  2. 滚动视口区域,到某一项内容区域,侧边栏选中状态也会跟着变化
typescript 复制代码
const SideBarAgain: React.FC<PopupProps> = (props) => {

  // 父组件传过来的值
  const { tabList } = props

  const mainElementRef = useRef<HTMLDivElement>(null)
  // 用来监听页面滚动事件
  const scroll = useScroll(mainElementRef);

  const mainElement = mainElementRef.current

  const state = useReactive({ activeKey: '1' });

  const handleScroll = (key?:string) => {
    
    // 滚动时,需要修改侧边栏选中状态
    // 过滤出元素顶部到视窗的距离大于0的元素
    const currentKey = tabList.filter((item: { key: string })=>{
      const element = document.getElementById(`anchor-${item.key}`)
        if (!element) return
        const rect = element.getBoundingClientRect()
        if (rect.top >= 0) {
          return item
        }
    })
    
    // 判断如果currentKey大于0,则选取第一个key值
    if(currentKey.length){
      state.activeKey = currentKey[0].key
    }else{
      state.activeKey = tabList[tabList.length-1].key
    }
     
    // 点击侧边栏传入的ID,并滚动到对应位置
    if(key){
      document.getElementById(`anchor-${key}`)?.scrollIntoView({behavior: "smooth"})
      state.activeKey = key
    }
  }

  useEffect(() => {
    if (!mainElement) return
    mainElement.addEventListener('scroll', () => handleScroll)
    return () => {
      mainElement.removeEventListener('scroll', () => handleScroll)
    }
  }, [])

  // 利用scroll的变化监听handleScroll
  useLayoutEffect(() =>  handleScroll,[scroll])

  return (
       <div className='sider'>
          <SideBar activeKey={state.activeKey} onChange={(key)=>handleScroll(key)}>
            {tabList.map((item: { key: string, title: string }) => (
              <SideBar.Item key={item.key} title={item.title} />
            ))}
          </SideBar>
          <div className='main' ref={mainElementRef}>
            {tabList.map((item: { key: string; title: string; text: string}) => (
              <div key={item.key} id={`anchor-${item.key}`} >
                <h2>{item.title}</h2>
                {item.text}
              </div>
            ))}
          </div>
       </div>
  )
}

export default SideBarAgain;
相关推荐
文心快码BaiduComate2 分钟前
里程碑突破 | 文心快码中标国家开发银行代码研发助手项目
前端·后端·架构
霍理迪11 分钟前
axios的封装
前端
夜焱辰12 分钟前
CreatorWeave:一个本地优先的浏览器 AI 创作工作空间
前端·agent
wscqs13 分钟前
Superpowers 与 everything-claude-code 与 ui-ux-pro-max-skill 这些怎么合并起来一起用
前端
大转转FE17 分钟前
转转前端周刊第192期: 财务数仓 Claude AI Coding 应用实战
前端·人工智能
weixin_471383031 小时前
React Flow + Zustand 搭建工作流编排工作台
前端·react.js·前端框架
kilito_011 小时前
react疑难讲解
前端·react.js·前端框架
字节跳动的猫1 小时前
2026 四款 AI:开发场景适配全面解析
前端·人工智能·开源
gyx_这个杀手不太冷静1 小时前
大人工智能时代下前端界面全新开发模式的思考(四)
前端·架构·ai编程
Ruihong1 小时前
你的 Vue 3 useAttrs(),VuReact 会编译成什么样的 React?
vue.js·react.js·面试