Next.js/ReactJS页面切换时Spline重复渲染问题咨询
Spline 3D页面切换后重复渲染问题解决方案
问题背景
我制作了Spline 3D设计并部署至网站,Spline本身运行正常,但页面切换时存在异常:从首页切换到关于页,再返回首页时,Spline会重复渲染。
现象说明
- 首页初始状态:Spline正常渲染
- 切换至关于页状态:Spline随首页组件卸载
- 返回首页状态:Spline重新加载,出现重复渲染
代码场景
使用Next.js App Router,首页page.tsx中直接引入Spline组件:
import Spline from '@splinetool/react-spline'; export default function Home() { return ( <main className="flex min-h-screen flex-col items-center justify-between p-24"> <Spline scene="https://prod.spline.design/xxxx/scene.splinecode" /> </main> ); }
核心原因
路由切换时,首页组件被完全卸载,返回时重新挂载,导致Spline组件从头初始化,出现重复渲染(实际是重新加载)。
可行解决方案
1. 缓存Spline组件(推荐)
用React.cache包裹Spline组件,确保组件实例在路由切换后复用:
import Spline from '@splinetool/react-spline'; // 缓存Spline组件实例 const CachedSpline = React.cache(() => ( <Spline scene="https://prod.spline.design/xxxx/scene.splinecode" /> )); export default function Home() { return ( <main className="flex min-h-screen flex-col items-center justify-between p-24"> <CachedSpline /> </main> ); }
2. 全局布局挂载+显隐控制
将Spline放到根布局layout.tsx中,通过CSS控制在不同页面的显示/隐藏,避免组件卸载:
// app/layout.tsx import { usePathname } from 'next/navigation'; import Spline from '@splinetool/react-spline'; import './globals.css'; export default function RootLayout({ children }: { children: React.ReactNode }) { const pathname = usePathname(); return ( <html lang="en"> <body> {/* 仅在首页显示Spline */} <div className={`spline-bg ${pathname !== '/' ? 'hidden' : ''}`}> <Spline scene="https://prod.spline.design/xxxx/scene.splinecode" /> </div> {children} </body> </html> ); }
对应的globals.css:
.spline-bg { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: -1; } .hidden { display: none; }
3. 手动管理Spline实例
通过useRef保存Spline实例,避免组件卸载时销毁实例:
import { useEffect, useRef } from 'react'; export default function Home() { const splineContainer = useRef<HTMLDivElement>(null); const splineInstance = useRef<any>(null); useEffect(() => { if (!splineInstance.current && splineContainer.current) { // 手动初始化Spline splineInstance.current = new window.SplineViewer(splineContainer.current, { scene: "https://prod.spline.design/xxxx/scene.splinecode" }); } // 组件卸载时不销毁实例(或者根据路由判断是否销毁) return () => {}; }, []); return ( <main className="flex min-h-screen flex-col items-center justify-between p-24"> <div ref={splineContainer} className="w-full h-full" /> </main> ); }
内容的提问来源于stack exchange,提问作者Azura
相关产品推荐
相关产品推荐

