自定义处理 vue 路由器 ID 中的正斜杠
Custom handling forward slashes in vue router ids
我有一个用例需要 vue 路由的 id 部分包含未转义的正斜杠。
我当前的路线是这样的:
{
path: '/browse/:path*',
component: browse,
name: 'browse',
displayName: 'Browse',
meta: { title: 'Browse' },
},
所以当用户浏览到上面的 url 时,将显示浏览组件。
但是,我想使用路径的 id 部分 (:path*
) 来包含一个可嵌套的文件系统,例如我的浏览页面要使用的路径。
例如 url /browse/project/project1
会在我的树中将我向下两层带到 project1 项。
现在,我 运行 遇到的问题是 vue 路由器在以编程方式导航时 escaping 我的 ID(路径),我的 url 最终像这样:/browse/project%2Fproject1
。这是不理想的,并且对最终用户来说看起来不太好。此外,如果用户确实手动浏览到 /browse/project/project1
,该应用程序将正常工作,甚至会在 url 栏中保留原始编码。
所以我可以通过创建任意数量的子路径来解决这个问题,并希望系统永远不会越过这些路径,但这不是解决我的问题的好方法。
我还应该澄清一下,应用程序将不知道 /browse
之后的路径,因为这是由为应用程序提供支持的 api 动态生成的。
vue-router 中是否有本地方式来处理这个问题?或者我应该改变我做事的方式。
我刚刚在遇到类似问题时偶然发现了你的问题。
认为这是因为 id 应标识一个资源而不是资源的嵌套 structure/path。
虽然我还没有解决我的问题,但您可能想要使用的是 customQueryString:
https://router.vuejs.org/api/#parsequery-stringifyquery
https://discourse.algolia.com/t/active-url-with-vue-router-for-facet-and-queries/3399
所以我设法 'fix' 通过一些 hack。
在创建我的 Vue 路由器实例时,我附加了一个 beforeEach
函数来替换“/”的任何传出编码。这会将我正在寻找的 'correct' URL 发送给客户端。
const router = new Router({
mode: 'history',
routes,
});
router.beforeEach((to, from, next) => {
// hack to allow for forward slashes in path ids
if (to.fullPath.includes('%2F')) {
next(to.fullPath.replace('%2F', '/'));
}
next();
});
我通过创建帮助器来为 vue 路由器 :to
属性生成 href 来修复它 link。
首先,我让路由器可以访问我的新助手服务,就像这里
然后我创建了router-helpers.js
,在这里我做了我的助手,这是一个例子
import Vue from 'vue'
import router from '../router.js'
// replace %2F in link by /
const hrefFixes = function(to) {
return to.replace(/%2F/g, '/')
}
// my link helper
Vue.prototype.$linkExample = attr => {
// create "to" object for router resolve
const to = { name: `route-name`, params: { param1: attr } }
// this will resolve "to" object, return href param as string
// and then i can replace %2F in that string
return hrefFixes(router.resolve(to).href)
}
只需在您的 Vue 应用程序中包含此服务一次,然后就可以像这样使用此助手
<router-link :to="$linkExample(attr)">text</router-link>
有一个没有变通办法的更优雅的解决方案。
Vue 路由器在幕后使用 path-to-regexp 模块和类似
的结构
const regexp = pathToRegexp('/browse/:path*')
// keys = [{ name: 'browse', delimiter: '/', optional: true, repeat: true }]
https://github.com/pillarjs/path-to-regexp#zero-or-more
const regexp = pathToRegexp('/browse/:path+')
// keys = [{ name: 'browse', delimiter: '/', optional: false, repeat: true }]
https://github.com/pillarjs/path-to-regexp#one-or-more
将重复 标记设置为true
。任何带有 repeat 标志的数组参数都将与分隔符连接(默认为 '/'
)。
因此您可以将拆分数组 ['project','project1']
而不是 'project/project1'
传递给 router.push()
:
router.push( {name: 'browse', params: {path: ['project','project1']}} );
或
router.push( {name: 'browse', params: {path: 'project/project1'.split('/')}} );
我有一个用例需要 vue 路由的 id 部分包含未转义的正斜杠。
我当前的路线是这样的:
{
path: '/browse/:path*',
component: browse,
name: 'browse',
displayName: 'Browse',
meta: { title: 'Browse' },
},
所以当用户浏览到上面的 url 时,将显示浏览组件。
但是,我想使用路径的 id 部分 (:path*
) 来包含一个可嵌套的文件系统,例如我的浏览页面要使用的路径。
例如 url /browse/project/project1
会在我的树中将我向下两层带到 project1 项。
现在,我 运行 遇到的问题是 vue 路由器在以编程方式导航时 escaping 我的 ID(路径),我的 url 最终像这样:/browse/project%2Fproject1
。这是不理想的,并且对最终用户来说看起来不太好。此外,如果用户确实手动浏览到 /browse/project/project1
,该应用程序将正常工作,甚至会在 url 栏中保留原始编码。
所以我可以通过创建任意数量的子路径来解决这个问题,并希望系统永远不会越过这些路径,但这不是解决我的问题的好方法。
我还应该澄清一下,应用程序将不知道 /browse
之后的路径,因为这是由为应用程序提供支持的 api 动态生成的。
vue-router 中是否有本地方式来处理这个问题?或者我应该改变我做事的方式。
我刚刚在遇到类似问题时偶然发现了你的问题。
认为这是因为 id 应标识一个资源而不是资源的嵌套 structure/path。
虽然我还没有解决我的问题,但您可能想要使用的是 customQueryString:
https://router.vuejs.org/api/#parsequery-stringifyquery
https://discourse.algolia.com/t/active-url-with-vue-router-for-facet-and-queries/3399
所以我设法 'fix' 通过一些 hack。
在创建我的 Vue 路由器实例时,我附加了一个 beforeEach
函数来替换“/”的任何传出编码。这会将我正在寻找的 'correct' URL 发送给客户端。
const router = new Router({
mode: 'history',
routes,
});
router.beforeEach((to, from, next) => {
// hack to allow for forward slashes in path ids
if (to.fullPath.includes('%2F')) {
next(to.fullPath.replace('%2F', '/'));
}
next();
});
我通过创建帮助器来为 vue 路由器 :to
属性生成 href 来修复它 link。
首先,我让路由器可以访问我的新助手服务,就像这里
然后我创建了router-helpers.js
,在这里我做了我的助手,这是一个例子
import Vue from 'vue'
import router from '../router.js'
// replace %2F in link by /
const hrefFixes = function(to) {
return to.replace(/%2F/g, '/')
}
// my link helper
Vue.prototype.$linkExample = attr => {
// create "to" object for router resolve
const to = { name: `route-name`, params: { param1: attr } }
// this will resolve "to" object, return href param as string
// and then i can replace %2F in that string
return hrefFixes(router.resolve(to).href)
}
只需在您的 Vue 应用程序中包含此服务一次,然后就可以像这样使用此助手
<router-link :to="$linkExample(attr)">text</router-link>
有一个没有变通办法的更优雅的解决方案。
Vue 路由器在幕后使用 path-to-regexp 模块和类似
的结构const regexp = pathToRegexp('/browse/:path*')
// keys = [{ name: 'browse', delimiter: '/', optional: true, repeat: true }]
https://github.com/pillarjs/path-to-regexp#zero-or-more
const regexp = pathToRegexp('/browse/:path+')
// keys = [{ name: 'browse', delimiter: '/', optional: false, repeat: true }]
https://github.com/pillarjs/path-to-regexp#one-or-more
将重复 标记设置为true
。任何带有 repeat 标志的数组参数都将与分隔符连接(默认为 '/'
)。
因此您可以将拆分数组 ['project','project1']
而不是 'project/project1'
传递给 router.push()
:
router.push( {name: 'browse', params: {path: ['project','project1']}} );
或
router.push( {name: 'browse', params: {path: 'project/project1'.split('/')}} );