Next.js 15服务端检测用户操作系统致动态页面,求简便解决方案
解决思路:不用动态页面,搞定无闪烁的OS适配快捷键
给你几个简单可行的方案,不用折腾中间件改URL导致页面变动态:
方案1:客户端组件用useLayoutEffect(无闪烁核心方案)
直接在客户端组件里用useLayoutEffect检测系统,这个钩子是在DOM渲染到页面之前同步执行的,完全不会出现水合闪烁问题:
'use client'; import { useLayoutEffect, useState } from 'react'; export default function ShortcutKey() { const [shortcut, setShortcut] = useState('Ctrl + K'); useLayoutEffect(() => { const isMac = navigator.userAgent.includes('Mac OS X'); setShortcut(isMac ? '⌘ + K' : 'Ctrl + K'); }, []); return <kbd>{shortcut}</kbd>; }
核心就是useLayoutEffect比普通useEffect执行时机更早,DOM还没展示给用户就已经设置好了正确的快捷键,看不到任何闪烁。
方案2:静态渲染双版本+内联脚本即时切换(全静态页面)
如果要保持页面完全静态生成,不想依赖客户端组件的状态逻辑,可以同时渲染两种快捷键,用内联脚本在页面加载时立即切换显示状态——内联脚本执行时机比React水合还早,用户直接看到对应系统的快捷键:
export default function Page() { return ( <div> <kbd className="windows-key">Ctrl + K</kbd> <kbd className="mac-key">⌘ + K</kbd> {/* 页面加载时立即执行的内联脚本 */} <script dangerouslySetInnerHTML={{ __html: ` const isMac = navigator.userAgent.includes('Mac OS X'); document.querySelector('.windows-key').style.display = isMac ? 'none' : 'inline'; document.querySelector('.mac-key').style.display = isMac ? 'inline' : 'none'; ` }} /> <style jsx>{` .windows-key, .mac-key { display: none; } `}</style> </div> ); }
这个方案下页面是完全静态生成的,没有动态渲染的额外开销。
方案3:纯CSS媒体查询适配(零JS方案)
利用浏览器对特定CSS规则的支持差异,不用写任何JS就能区分系统,兼容性覆盖绝大多数主流浏览器:
/* 全局样式 */ :root { --show-mac: none; --show-windows: inline; } /* Windows系统下的Chrome/Edge/IE会命中这个规则 */ @media (min-width: 0\0) { :root { --show-mac: none; --show-windows: inline; } } /* Mac系统下的Safari/Chrome会命中这个规则 */ @supports (-webkit-appearance: none) and (stroke-color: transparent) { :root { --show-mac: inline; --show-windows: none; } } .windows-key { display: var(--show-windows); } .mac-key { display: var(--show-mac); }
然后组件里直接渲染两个快捷键即可:
export default function ShortcutKey() { return ( <> <kbd className="windows-key">Ctrl + K</kbd> <kbd className="mac-key">⌘ + K</kbd> </> ); }
内容的提问来源于stack exchange,提问作者Orkhan Fattayev
相关产品推荐
相关产品推荐

