前言
【vue-router源码】系列文章将带你从0开始了解vue-router
的具体实现。该系列文章源码参考vue-router v4.0.15
。
源码地址:https://github.com/vuejs/router
阅读该文章的前提是你最好了解vue-router
的基本使用,如果你没有使用过的话,可通过vue-router官网学习下。
该篇文章将分析RouterLink
组件的实现。
使用
<RouterLink
to="/inex"
reaplace
custom
activeClass="active"
exactActiveClass="exact-active"
ariaCurrentValue="page"
>To Index Page</RouterLink>
RouterLink
export const RouterLinkImpl = /*#__PURE__*/ defineComponent({
name: 'RouterLink',
props: {
// 目标路由的链接
to: {
type: [String, Object] as PropType<RouteLocationRaw>,
required: true,
},
// 决定是否调用router.push()还是router.replace()
replace: Boolean,
// 链接被激活时,用于渲染a标签的class
activeClass: String,
// inactiveClass: String,
// 链接精准激活时,用于渲染a标签的class
exactActiveClass: String,
// 是否不应该将内容包裹在<a/>标签中
custom: Boolean,
// 传递给aria-current属性的值。https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current
ariaCurrentValue: {
type: String as PropType<RouterLinkProps['ariaCurrentValue']>,
default: 'page',
},
},
useLink,
setup(props, { slots }) {
// 使用useLink创建router-link所需的一些属性和行为
const link = reactive(useLink(props))
// createRouter时传入的options
const { options } = inject(routerKey)!
// class对象
const elClass = computed(() => ({
[getLinkClass(
props.activeClass,
options.linkActiveClass,
'router-link-active'
)]: link.isActive, // 被激活时的class
[getLinkClass(
props.exactActiveClass,
options.linkExactActiveClass,
'router-link-exact-active'
)]: link.isExactActive, // 被精准激活的class
}))
return () => {
// 默认插槽
const children = slots.default && slots.default(link)
// 如果设置了props.custom,直接显示chldren,反之需要使用a标签包裹
return props.custom
? children
: h(
'a',
{
'aria-current': link.isExactActive
? props.ariaCurrentValue
: null,
href: link.href,
onClick: link.navigate,
class: elClass.value,
},
children
)
}
},
})
export const RouterLink = RouterLinkImpl as unknown as {
new (): {
$props: AllowedComponentProps &
ComponentCustomProps &
VNodeProps &
RouterLinkProps
$slots: {
default: (arg: UnwrapRef<ReturnType<typeof useLink>>) => VNode[]
}
}
useLink: typeof useLink
}
网友评论