Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert RouterLink to functional component #2626

Closed
olavoasantos opened this Issue Feb 25, 2019 · 2 comments

Comments

Projects
None yet
2 participants
@olavoasantos
Copy link

olavoasantos commented Feb 25, 2019

What problem does this feature solve?

As this is a simple component which doesn't use state and can be used in several places on the application, the conversion to a functional component could generate performance improvements for the application.

What does the proposed API look like?

The RouterLink component API would not change. The conversion can easily be done by modifying the ./src/components/link.js component to:

export default {
  name: 'RouterLink',
  props: { /**...*/ },
  functional: true,
  render (h, { parent, props, children }) {
    const router = parent.$router
    const current = parent.$route
    const { location, route, href } = router.resolve(props.to, current, props.append)

    const classes = {}
    const globalActiveClass = router.options.linkActiveClass
    const globalExactActiveClass = router.options.linkExactActiveClass

    const activeClassFallback = globalActiveClass == null
      ? 'router-link-active'
      : globalActiveClass
    const exactActiveClassFallback = globalExactActiveClass == null
      ? 'router-link-exact-active'
      : globalExactActiveClass
    const activeClass = props.activeClass == null
      ? activeClassFallback
      : props.activeClass
    const exactActiveClass = props.exactActiveClass == null
      ? exactActiveClassFallback
      : props.exactActiveClass
    const compareTarget = location.path
      ? createRoute(null, location, null, router)
      : route

    classes[exactActiveClass] = isSameRoute(current, compareTarget)
    classes[activeClass] = props.exact
      ? classes[exactActiveClass]
      : isIncludedRoute(current, compareTarget)

    const handler = e => {
      if (guardEvent(e)) {
        if (props.replace) {
          router.replace(location)
        } else {
          router.push(location)
        }
      }
    }

    const on = { click: guardEvent }
    if (Array.isArray(props.event)) {
      props.event.forEach(e => { on[e] = handler })
    } else {
      on[props.event] = handler
    }

    const data = {
      class: classes
    }

    if (props.tag === 'a') {
      data.on = on
      data.attrs = { href }
    } else {
      const a = findAnchor(children)
      if (a) {
        a.isStatic = false
        const aData = a.data = extend({}, a.data)
        aData.on = on
        const aAttrs = a.data.attrs = extend({}, a.data.attrs)
        aAttrs.href = href
      } else {
        data.on = on
      }
    }

    return h(props.tag, data, children)
  }
}
@posva

This comment has been minimized.

Copy link
Member

posva commented Feb 25, 2019

Thanks for the proposal but this has been already discussed (there is even a PR opened) and it would break some behaviours of vue router making it a breaking change

@posva posva closed this Feb 25, 2019

@olavoasantos

This comment has been minimized.

Copy link
Author

olavoasantos commented Feb 25, 2019

Sorry about that. Tried searching but didn't find it. Thanks for answering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.