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

Make route name map part of public API #2829

Closed
Etheryte opened this issue Jun 26, 2019 · 1 comment
Closed

Make route name map part of public API #2829

Etheryte opened this issue Jun 26, 2019 · 1 comment

Comments

@Etheryte
Copy link

Etheryte commented Jun 26, 2019

What problem does this feature solve?

Working with large-scale applications, a fairly common problem when using vue-router is trying to avoid inline string constants for link definitions and programmatic navigation. For example:

<router-link to="/documents">Documents</router-link>

and

this.$router.push("/documents");

Inline constants like these are subject to rot over time, human error when refactoring multiple documents and other similar errors. As an application grows in size, these issues become more prominent.

What does the proposed API look like?

As a solution, our shop often uses a mapping from route name to a route definition. Sample implementation:

interface IRouteMap {
  [key: string]: ReturnType<Router['resolve']> & { name: string };
}

function mapRoutes(routeMap: IRouteMap, routes: RouteConfig[] = []) {
  return routes.reduce((map, route) => {
    const name = route.name;
    if (name) {
      map[name] = Object.assign({
        name,
      }, router.resolve(name));
    }
    if (route.children) {
      mapRoutes(map, route.children);
    }
    return map;
  }, routeMap);
}

export const routeMap = mapRoutes({}, routes);

Links and navigation can then simply use the resulting mapping:

<router-link v-bind:to="routeMap.documents.location">Documents</router-link>

and

this.$router.push(routeMap.documents.location);

or

router.beforeEach((to, from, next) => {
  if (to.name !== routeMap.login.name && !store.state.user) ...
});

This means that changing a route's path requires a single change in the route definition itself and no further refactoring is necessary. Route names are internal and aren't subject to change over time as route paths often can be.

Adding a similar mapping (or exposing existing internals) to vue-router's public API would provide a standardized solution to the given problem and allow all vue-router consumers to reap the benefits.

@posva
Copy link
Member

posva commented Jun 26, 2019

I see the point but there is a major flaw and it's that not all routes can be passed like that: A route with a param will have a path (there is no location in a record) value with a colon in it.

This won't be a problem once we have more props on router-link: #2818

As for router.push, it's very easy to add a custom function:

VueRouter.prototype.pushNamed = function pushNamed (name, ...args) {
  return this.push({ name }, ...args)
}

@posva posva closed this as completed Jun 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants