关于前端:vuerouter源码十三RouterLink源码分析

35次阅读

共计 1829 个字符,预计需要花费 5 分钟才能阅读完成。

前言

【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
}

正文完
 0