Docusaurus:Swizzle Navbar实现不同版本导航项显示控制
可行性说明
完全不需要Eject,用Swizzle的Wrapping模式就能实现。这种方式不会修改官方原始组件代码,既能保留自定义逻辑,还能兼容后续官方的组件更新,比Eject靠谱得多。
实现流程(基于已Swizzle的Navbar/NavbarItem组件)
获取当前文档版本
在你Swizzle后的Navbar组件文件(一般是src/theme/Navbar.js)中,引入Docusaurus的版本上下文钩子,用来获取当前浏览的文档版本:import { useVersionContext } from '@docusaurus/plugin-content-docs/client';然后在组件内部解构获取版本号:
const { version } = useVersionContext();编写版本对比逻辑
写一个简单的工具函数,用来判断当前版本是否大于等于目标版本(这里是1.3.0):const isVersionGreaterOrEqual = (currentVersion, targetVersion) => { const currentParts = currentVersion.split('.').map(Number); const targetParts = targetVersion.split('.').map(Number); for (let i = 0; i < Math.max(currentParts.length, targetParts.length); i++) { const curr = currentParts[i] || 0; const target = targetParts[i] || 0; if (curr > target) return true; if (curr < target) return false; } return true; // 版本完全相同时返回true };接着用这个函数判断是否要显示新版导航:
const showNewNavbar = isVersionGreaterOrEqual(version, '1.3.0');动态渲染导航项
在Navbar的Wrapper组件中,根据showNewNavbar的值,分别定义不同版本对应的导航项,再注入到原始Navbar的props中:import Navbar from '@theme-original/Navbar'; import { useVersionContext } from '@docusaurus/plugin-content-docs/client'; import NavbarDropdown from '@theme/NavbarDropdown'; import NavbarItem from '@theme/NavbarItem'; export default function NavbarWrapper(props) { const { version } = useVersionContext(); const isVersionGreaterOrEqual = (currentVersion, targetVersion) => { const currentParts = currentVersion.split('.').map(Number); const targetParts = targetVersion.split('.').map(Number); for (let i = 0; i < Math.max(currentParts.length, targetParts.length); i++) { const curr = currentParts[i] || 0; const target = targetParts[i] || 0; if (curr > target) return true; if (curr < target) return false; } return true; }; const showNewNavbar = isVersionGreaterOrEqual(version, '1.3.0'); // 定义不同版本对应的导航项 const customNavItems = showNewNavbar ? [ <NavbarDropdown label="Dropdown B" key="dropdown-b"> <NavbarItem to="/docs/v1.3.0/guide">新指南</NavbarItem> <NavbarItem to="/docs/v1.3.0/api">新API</NavbarItem> </NavbarDropdown>, <NavbarItem to="/docs/v1.3.0/changelog" key="changelog">更新日志</NavbarItem> ] : [ <NavbarDropdown label="Dropdown A" key="dropdown-a"> <NavbarItem to="/docs/v1.2.0/basic">基础使用</NavbarItem> <NavbarItem to="/docs/v1.2.0/troubleshoot">问题排查</NavbarItem> </NavbarDropdown> ]; // 合并自定义导航项与原始导航项,渲染Navbar return <Navbar {...props} items={[...customNavItems, ...props.items]} />; }- 如果你的项目原本有默认导航项,
...props.items会保留这些项,你可以调整自定义项和原始项的顺序(比如把自定义项放在后面就改成[...props.items, ...customNavItems])。
- 如果你的项目原本有默认导航项,
测试验证
切换不同版本的文档,检查Navbar显示:1.2.0及以下版本仅显示Dropdown A,1.3.0及以上版本显示Dropdown B和额外的导航项。
注意事项
- Swizzle时一定要选Wrap模式,不要选Eject。Wrap模式是在官方组件外层包裹自定义逻辑,后续官方更新Navbar组件时,你的代码不会被覆盖;而Eject会把官方组件代码完全复制到本地,后续无法接收官方更新,维护成本极高。
- 如果之前不小心Swizzle成了Eject模式,建议重新执行Swizzle命令,选择Wrap模式覆盖。
内容的提问来源于stack exchange,提问作者Aneesha S
相关产品推荐
相关产品推荐

