You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Remix.run(TypeScript)中实现区块滚动导航功能?

Remix.run + TypeScript 区块滚动导航实现方案

问题分析

你之前的scrollTo函数报错,核心原因有两个:

  1. TypeScript严格模式下,document.getElementById()可能返回null,直接调用scrollIntoView()会触发类型错误
  2. Remix是服务端渲染框架,服务端环境没有document对象,若代码在服务端执行会抛出异常

修复与集成步骤

1. 安全的滚动函数实现

先编写兼容TypeScript和SSR环境的滚动函数:

const scrollToSection = (sectionId: string) => {
  // 确保仅在客户端执行代码
  if (typeof window === 'undefined') return;
  
  const section = document.getElementById(sectionId);
  // 空值检查,避免类型错误与运行时异常
  if (section) {
    // 可选:添加平滑滚动提升体验
    section.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }
};

2. 集成到App根组件

将滚动功能集成到你的App组件中,同时添加导航按钮示例:

import { Links, Meta, Outlet, Scripts } from "@remix-run/react";
import { useCallback } from "react";

export default function App() {
  // 用useCallback缓存函数,避免组件重渲染时重复创建
  const scrollToSection = useCallback((sectionId: string) => {
    if (typeof window === 'undefined') return;
    const section = document.getElementById(sectionId);
    if (section) {
      section.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  }, []);

  return (
    <html>
      <head>
        <link rel="icon" href="data:image/x-icon;base64,AA" />
        <Meta />
        <Links />
      </head>
      <body>
        <h1>Hello world!</h1>
        
        {/* 导航按钮区域 */}
        <nav style={{ margin: "1rem 0" }}>
          <button onClick={() => scrollToSection("section1")} style={{ marginRight: "0.5rem" }}>
            跳转到区块1
          </button>
          <button onClick={() => scrollToSection("section2")}>
            跳转到区块2
          </button>
        </nav>
        
        <Outlet />
        <Scripts />
      </body>
    </html>
  );
}

3. 路由页面添加目标区块

在Outlet对应的路由页面(比如routes/sections.tsx)中添加带id的目标区块:

export default function SectionsPage() {
  return (
    <div>
      <section id="section1" style={{ height: "800px", backgroundColor: "#f0f0f0", margin: "1rem 0" }}>
        <h2>区块1</h2>
      </section>
      <section id="section2" style={{ height: "800px", backgroundColor: "#e0e0e0", margin: "1rem 0" }}>
        <h2>区块2</h2>
      </section>
    </div>
  );
}

最优方案补充

如果目标区块是固定且可控的,也可以用React的useRef替代全局DOM查询,性能更优:

import { useRef, useCallback } from "react";

export default function SomeComponent() {
  const section1Ref = useRef<HTMLElement>(null);
  
  const scrollToSection1 = useCallback(() => {
    section1Ref.current?.scrollIntoView({ behavior: "smooth" });
  }, []);

  return (
    <>
      <button onClick={scrollToSection1}>跳转到区块1</button>
      <section ref={section1Ref}>
        <h2>区块1</h2>
      </section>
    </>
  );
}

内容的提问来源于stack exchange,提问作者BigChungus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 11:30:07