Vue Router:保留查询参数并为子级使用相同的视图
Vue Router: Keep query parameter and use same view for children
我正在用 Vue 重写现有的 Angular 1 个应用程序。
应用程序 总是 需要在进入任何视图之前通过 locale
、id
和 token
对用户进行身份验证。尊重我们 API 的约定,我将 token
指定为我的主要父路由中的查询参数。
来自现有的 Angular 的 UI 路由器实现,我认为这是要走的路:
// main.js
new Vue({
el: '#app',
router,
store,
template: '<router-view name="main"></router-view>'
})
// router.js
const router = new Router({
mode: 'history',
routes: [
{
name: 'start',
path : '/:locale/:id', // /:locale/:id?token didn't work
query: {
token: null
},
beforeEnter (to, from, next) {
// 1. Get data from API via locale, id and token
// 2. Update store with user data
},
components: {
main: startComponent
},
children: [{
name: 'profile',
path: 'profile',
components: {
main: profileComponent
}
}]
}
]
})
当我导航到 profile
视图时,我希望视图发生变化并且查询令牌保持不变,例如/en-US/123?token=abc
到 /en-US/123/profile?token=abc
。两者都没有。
我正在使用 Vue 2.3.3 和 Vue Router 2.3.1。
问题:
- 导航到子路由时可以保留查询参数吗?
- 我在这里使用的是 Vue 路由器吗?还是我需要责怪我的 UI 路由器偏见?
你可以在路由器的全局钩子中解决这个问题
import VueRouter from 'vue-router';
import routes from './routes';
const Router = new VueRouter({
mode: 'history',
routes
});
function hasQueryParams(route) {
return !!Object.keys(route.query).length
}
Router.beforeEach((to, from, next) => {
if(!hasQueryParams(to) && hasQueryParams(from)){
next({name: to.name, query: from.query});
} else {
next()
}
})
如果新路由(to
)没有自己的参数,那么它们将取自之前的路由(from
)
你可以添加一个 mounted
挂钩路由器导航守卫 beforeEach
像这样 preserveQueryParams
:
// helpers.js
import isEmpty from 'lodash/isEmpty';
const preserveQueryParams = (to, from, next) => {
const usePreviousQueryParams = isEmpty(to.query) && !isEmpty(from.query);
if (usePreviousQueryParams) {
next({ ...to, query: from.query });
} else {
next();
}
};
// StartComponent.vue
removeBeforeEachRouteGuard: Function;
mounted() {
this.removeBeforeEachRouteGuard = this.$router.beforeEach(preserveQueryParams);
}
// don't forget to remove created guard
destroyed() {
this.removeBeforeEachRouteGuard();
// resetting query can be useful too
this.$router.push({ query: {} });
}
我正在用 Vue 重写现有的 Angular 1 个应用程序。
应用程序 总是 需要在进入任何视图之前通过 locale
、id
和 token
对用户进行身份验证。尊重我们 API 的约定,我将 token
指定为我的主要父路由中的查询参数。
来自现有的 Angular 的 UI 路由器实现,我认为这是要走的路:
// main.js
new Vue({
el: '#app',
router,
store,
template: '<router-view name="main"></router-view>'
})
// router.js
const router = new Router({
mode: 'history',
routes: [
{
name: 'start',
path : '/:locale/:id', // /:locale/:id?token didn't work
query: {
token: null
},
beforeEnter (to, from, next) {
// 1. Get data from API via locale, id and token
// 2. Update store with user data
},
components: {
main: startComponent
},
children: [{
name: 'profile',
path: 'profile',
components: {
main: profileComponent
}
}]
}
]
})
当我导航到 profile
视图时,我希望视图发生变化并且查询令牌保持不变,例如/en-US/123?token=abc
到 /en-US/123/profile?token=abc
。两者都没有。
我正在使用 Vue 2.3.3 和 Vue Router 2.3.1。
问题:
- 导航到子路由时可以保留查询参数吗?
- 我在这里使用的是 Vue 路由器吗?还是我需要责怪我的 UI 路由器偏见?
你可以在路由器的全局钩子中解决这个问题
import VueRouter from 'vue-router';
import routes from './routes';
const Router = new VueRouter({
mode: 'history',
routes
});
function hasQueryParams(route) {
return !!Object.keys(route.query).length
}
Router.beforeEach((to, from, next) => {
if(!hasQueryParams(to) && hasQueryParams(from)){
next({name: to.name, query: from.query});
} else {
next()
}
})
如果新路由(to
)没有自己的参数,那么它们将取自之前的路由(from
)
你可以添加一个 mounted
挂钩路由器导航守卫 beforeEach
像这样 preserveQueryParams
:
// helpers.js
import isEmpty from 'lodash/isEmpty';
const preserveQueryParams = (to, from, next) => {
const usePreviousQueryParams = isEmpty(to.query) && !isEmpty(from.query);
if (usePreviousQueryParams) {
next({ ...to, query: from.query });
} else {
next();
}
};
// StartComponent.vue
removeBeforeEachRouteGuard: Function;
mounted() {
this.removeBeforeEachRouteGuard = this.$router.beforeEach(preserveQueryParams);
}
// don't forget to remove created guard
destroyed() {
this.removeBeforeEachRouteGuard();
// resetting query can be useful too
this.$router.push({ query: {} });
}