Open nicbou opened 7 years ago
Additional information:
If I try to use a string in router.push, it gets escaped.
I also found a related ticket: https://github.com/pillarjs/path-to-regexp/issues/80
Hi @nicbou
Thanks for the report. Could you provide an interactive reproduction via jsfiddle or a quick repository? That would help us out.
Yes of course! Here is a demo: http://jsfiddle.net/ub9e33fm/1/
As you can see, you can only update the path with an array due to escaping, but it is always initially loaded as a string.
Would you mind changing the ticket label? The repro is right above :)
I'm checking the repro, thanks for the reminder
@nicbou I checked the repro but it looks good to me:
/foo/bar
string -> one single param foo parsed path: /foo/bar
/bar/baz
/
-> params is a string, path is escaped: /bar%2Fbaz
What is wrong?
The biggest issue for me is that the page gives me an a string as the param when the page loads, but if I navigate to that same URL programmatically, I get an array. The same URL and route resolve to different parameters. There is no way to navigate to that route and get a string as the params (as it gets escaped).
This is a bug because these should behave consistently and they don't. I would naturally expect an array since there are multiple values for the same parameters, but a string would be trivial to parse too. It just cannot be both at the same time.
In our application, we currently need to do a if Array.isArray(params)
to prevent the application from breaking when the param is a string. Although this workaround works, it will need to be applied in multiple places as the application grows.
Additional details: the value can also be undefined
if you navigate to a link without passing the params (which are optional!)
Here is the updated JSFiddle: http://jsfiddle.net/ub9e33fm/3/
Here's the full workaround I need if I want to deal with an array as expected:
let urlItineraryItems = to.params.itineraryItems;
if (!Array.isArray(urlItineraryItems)) {
// https://github.com/vuejs/vue-router/issues/1175
urlItineraryItems = (urlItineraryItems || '').split('/')
}
I revisited the example and it's true that if we change the path
to path: '/:foo*'
(with the (.*)
, things are working as expected because the /
is no longer a delimiter), a link to /foo/baz
should yield a param foo: ['foo', 'baz']
.
I would still consider it a bug, as there is no way to obtain a consistent behaviour (params only as a string, or only as an array) with these "zero or more" matchers. I tried the same JSFiddle with the link updated, and I cannot get an array consistently.
In any case, the workaround I have posted works consistently well. If we end up committing to Vue (not my decision), I'll have a look. I suspect it's a bug with path-to-regexp that just carried over to vue-router.
I'm also facing this issue. The array trick works but the inconsistency is annoying to handle. I was expecting the zero or more match would always return an array, and that I would always use an array when pushing new routes programatically.
Vue.js / vue-router versions
2.1.1
Steps to reproduce
'/directions/:itineraryItems(.*)*'
/directions/origin/destination
What is Expected?
The parsed itineraryItems route param is an array containing 'origin' and 'destination'.
What is actually happening?
The parsed itineraryItems route param is a string with the value 'origin/destination' if the URL is accessed directly.
The parsed itineraryItems route param is an array containing 'origin' and 'destination' if accessed programmatically.
This means the same URL can have its params as an array or as a string, depending on how it was created.