第一种写法使用的是追加searchParams的方式,具体可以查看我的前一篇文章。
本文中的这种写法是通过useMatch, useResolvedPath两个钩子实现的,也是官网推荐的写法
// 定制化一个link
function MyLink ({ children, to, ...props }) {
let resolved = useResolvedPath(to);
// 看官网的说明,真正的路径应该是一个path对象,而不是一个字符串那么简单
// useResolvedPath会将to这个路径的字符串变成path能够识别的形式
let active = useMatch({ path: resolved.pathname, end: true });
// usematch暂时还没找到具体的说明,似乎是如果参数对象中的path和本页面的path相同,则返回true,参数对象中的end目前意义不明
return (
<div>
<Link
style={{ color: active ? "green" : "orange" }}
to={to}
{...props}
>
{children}
</Link>
</div>
);
}
上面的本质也就是通过两个钩子去判断是否跳转到了正确的路径
下面是一个整体组件,如果再outlet之中出现的页面和to属性match,nam在mylink组件之中active就会变成true
export default function CustomLink () {
// 选中的路由会因为active属性变成绿色
//下面的to属性需要注意一下,这个first和second实际上是上面CustomLink的子路由
return (
<>
<MyLink to={'/customlink/first'}>第一个链接</MyLink>
<MyLink to={'/customlink/second'}>第二个链接</MyLink>
<Outlet />
</>
)
}
export function First () {
return (
<p>我是第一个链接</p>
)
}
export function Second () {
return (
<p>我是第二个链接</p>
)
}
上面是customLink的两个子组件
这里有一个重要的总结:和上一篇文章中追加searchParams的方式的不同(强烈建议我一般的初学者看一看上一篇文章),追加searchParams的方式的判断的是link的属性,也就是说即使没有实际定义两个子组件,也会激活active属性。但是这种方法中,实际上似乎是一定要有两个子组件定义出来才行(相关规则和子组件一定要定义),原谅我的表达能力有限。