Vue-router: Parameter prefix/suffix

Created on 15 May 2016  路  12Comments  路  Source: vuejs/vue-router

Is it possible to extend the functionality of the parameters, to support prefix and/or suffix?

For example:

router.map({
  '/prefix{param}suffix': {
    component: Foo
  }
})
improvement

Most helpful comment

FYI this can be done in 2.0 as /(@):username

All 12 comments

What's the use case for this? Why not just:

router.map({
  '/prefix/:param/suffix': {
    component: Foo
  }
})

For example, in medium.com they have the user profiles like medium.com/@johndoe.

router.map({
  '/@{username}': {
    component: Profile
  }
}

The reason to prefix with an @ is to not match all the routes, because you will never end with 404 routes...

I want something like that as described by @NicolasParada.

Currently, I'm using that:

router.map({

  ...

  '/:username': {
    component (resolve) {
      require(['pages/Profile'], resolve)
    },
    before ({ to, next, redirect }) {
      if (to.params.username.startsWith('~')) {
        next()
      } else {
        redirect('/not-found')
      }
    }
  }
})

router.beforeEach((transition) => {
  if (transition.to.before) {
    transition.to.before(transition)
  } else {
    transition.next()
  }
})

Note that the /:username constitutes the last route, to match all paths with 1 segment.

However, I believe that other users need this functionality, which is why I raised this issue. :)

Ahh, I see how that makes sense - and does sound useful! If either of you feel like tackling it, I don't believe introducing this feature should be too hard. We'd just need an additional matcher for dynamic segments.

What about something like this?

if (match = segment.match(/^\{(?:[^\/:]?[^\/:a-zA-Z]{1})\}:([^\/:]+)$/)) {
  results.push(new DynamicSegment(match[1]))
  names.push(match[1])
  specificity.val += '3'
}

See gist - See regex

This would enable route constructs such as:

router.map({
  '/{@}:username': {
    // example.com/@johnDoe
    component: Profile
  },
  '/{_}:username': {
    // example.com/_johnDoe
    component: Profile
  },
  '/{myPrefix_}:username': {
    // example.com/myPrefix_johnDoe
    component: Profile
  },
  '/{56}:username': {
    // example.com/56johnDoe
    component: Profile
  }
}

The proposed regex only allows prefixes with no / and :, and not ending by any letter. Without those limitations, it seems to me that matching an url to a route path would be difficult/expensive (think of a abc prefix and trying to match example.com/abcjohnDoe with the correct path, and try not to have nightmares tonight).

Also, I think it should be better to keep the :param syntax for consistency reasons. So I suggest to wrap the prefix inside { }, instead of the parameter.

@chrisvfritz in addition to parsing route paths, where should go the code to match a given url to a path?

The code I suggested above just makes {prefix_}:param a valid route path and registers its dynamic segment, but I don't think it automagically makes example.com/prefix_johnDoe point to this path with johnDoe as the requested dynamic segment.

Or does it?

@JivanRoquet Thank you for your proposal, that would certainly do the job I think. the syntax with the curly braces feels a bit hackish to me though, maybe we can think of something more readable?

About your question concering the code the code for matching an url to a path: I think you were already in the right place.

The Route class (/src/route.js) uses the recognizer to match the current URL to a route and deconstruct params etc from the matched result. Those are used in the transition to the component etc.

@LinusBorg thanks for the follow-up. Would something like this be more readable?

router.map({
  '/@:username': {
    // example.com/@johnDoe
    component: Profile
  },
  '/_:username': {
    // example.com/_johnDoe
    component: Profile
  },
  '/myPrefix_:username': {
    // example.com/myPrefix_johnDoe
    component: Profile
  },
  '/56:username': {
    // example.com/56johnDoe
    component: Profile
  }
}

The associated regex being ^(?:[^\/:]?[^\/:a-zA-Z]{1}):([^\/:]+)$

Right now I don't think of any side-effect that would potentially trump the matching algorithm but there might be, and this would have to be thoroughly tested.

As a sidenote, I think an enclosed parameter syntax would be more secure, generally speaking, less confusing and more easily identifiable and pluggable with such prefixes/suffixes.

For instance, instead of :param/:otherParam we could have <param>/<otherParam> (more a Flask-way), which could also allow easier future param validation such as <param:string>/<otherParam:int>. But this is a broader topic...

Yes, this feature is important!

I hope to have something like /@{username} in Laravel.

FYI this can be done in 2.0 as /(@):username

FYI this can be done in 2.0 as /(@):username

Does this also apply to suffixes? Ie, can we use /:username(@)?

This thread is quite outdated now. Here are the up to date ways to do it

  • prefix: /@:username
  • suffix with slash /:something/suffix (/hello/suffix -> { something: 'hello' })
  • suffix with two params /:something:suffix(suffix) the param suffix only matches against suffix
  • suffix with custom regex: /:something([^/]+@suffix) (/hello@suffix -> { something: 'hello@suffix' }). Then clear it out with the props option on route records https://router.vuejs.org/guide/essentials/passing-props.html
Was this page helpful?
0 / 5 - 0 ratings

Related issues

sqal picture sqal  路  3Comments

Atinux picture Atinux  路  3Comments

saman picture saman  路  3Comments

yyx990803 picture yyx990803  路  3Comments

thomas-alrek picture thomas-alrek  路  3Comments