10 advanced tips for Vue Router

皮小蛋
中文

Preface

Vue Router is the official route manager Vue.js

It is deeply integrated with the core of Vue.js, making it easy to build single-page applications.

The functions included are:

  • Nested routing/view table
  • Modular, component-based routing configuration
  • Routing parameters, queries, wildcards
  • View transition effect based on Vue.js transition system
  • Fine-grained navigation control
  • Link with automatically activated CSS class
  • HTML5 history mode or hash mode, automatically downgraded in IE9
  • Custom scroll bar behavior

This article is a summary of the author encountered in actual projects, mainly including:

  1. responds to routing parameter changes
  2. route matching
  3. advanced matching mode
  4. match priority
  5. Push and replace the second and third parameters
  6. route view
  7. redirect
  8. Use props to decouple $route
  9. navigation guard
  10. guard's next method

Hope this article is helpful to you.

text

1. Respond to changes in routing parameters

For reused components (only the routing parameters are changed), the life cycle function hook will not be called, how can the component be refreshed?

  • watch
watch: {
    '$route' (to, from) {
    // 对路由变化作出响应...
    }
}
  • beforeRouteUpdate
beforeRouteUpdate (to, from, next) {
  // react to route changes...
/ / don't forget to call next()
}

2. Route matching

{
  // 会匹配所有路径
  path: '*'
}
{
  // 会匹配以 `/user-` 开头的任意路径
  path: '/user-*'
}

Note: When using wildcard routing, please make sure that the order of the routing is correct, which means that the routing with wildcards should be placed last. The route {path:'*'} is usually used for client 404 errors.

If you use History mode, make sure to configure your server correctly.

When a wildcard is used, a parameter named pathMatch is automatically added to $route.params.

It contains the part of the URL that is matched by wildcards:

// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'

3. Advanced matching mode

// 命名参数必须有"单个字符"[A-Za-z09]组成
 
// ?可选参数
{ path: '/optional-params/:foo?' }
// 路由跳转是可以设置或者不设置foo参数,可选
<router-link to="/optional-params">/optional-params</router-link>
<router-link to="/optional-params/foo">/optional-params/foo</router-link>
 
// 零个或多个参数
{ path: '/optional-params/*' }
<router-link to="/number">没有参数</router-link>
<router-link to="/number/foo000">一个参数</router-link>
<router-link to="/number/foo111/fff222">多个参数</router-link>
 
 
// 一个或多个参数
{ path: '/optional-params/:foo+' }
<router-link to="/number/foo">一个参数</router-link>
<router-link to="/number/foo/foo111/fff222">多个参数</router-link>
 
// 自定义匹配参数
// 可以为所有参数提供一个自定义的regexp,它将覆盖默认值([^\/]+)
{ path: '/optional-params/:id(\\d+)' }
{ path: '/optional-params/(foo/)?bar' }

4. Match priority

Sometimes a path may match multiple routes.

At this time, the priority of matching is based on the order of route definition: firstly defined, the highest priority.

5. The second and third parameters of push and replace

In version 2.2.0+, optionally provide onComplete and onAbort callbacks as the second and third parameters in router.push or router.replace.

These callbacks will be called when the navigation is successfully completed (after all asynchronous hooks are resolved) or terminated (navigated to the same route, or navigated to a different route before the current navigation is completed). In 3.1.0+, the second and third parameters can be omitted. At this time, if Promise is supported, router.push or router.replace will return a Promise.

Let's look at a few examples to see when the second and third parameters are called:

1. Component 1 Jump Component 2

// 组件1
this.$router.push({ name: 'number' }, () => {
  console.log('组件1:onComplete回调');
}, () => {
  console.log('组件1:onAbort回调');
});
// 组件2
beforeRouteEnter(to, from, next) {
  console.log('组件2:beforeRouteEnter');
  next();
},
beforeCreate() {
  console.log('组件2:beforeCreate');
},
created() {
  console.log('组件2:created');
}

Jumping between components triggers the onComplete callback.

2. Component 2 jumps to component 2 (without parameters)

this.$router.push({ name: 'number'}, () => {
  console.log('组件2:onComplete回调');
}, () => {
  console.log('组件2,自我跳转:onAbort回调');
});

The onAbort callback is triggered when the component self-jumps without parameters. But when the self-jump takes parameters, the situation may be a little different.

3. Component 2 jumps to component 2 (with parameters)

this.$router.push({ name: 'number', params: { foo: this.number}}, () => {
    console.log('组件2:onComplete回调');
}, () => {
    console.log('组件2,自我跳转:onAbort回调');
});

The component jumps with its own parameters, and neither the onComplete callback nor the onAbort callback callback will be triggered.

6. Route View

Sometimes you want to display multiple views at the same time (same level) instead of nested displays. For example, create a layout with two views, sidebar (side navigation) and main (main content). At this time, named views come in handy.

You can have multiple individually named views in the interface instead of just a single outlet.

If router-view does not set a name, it will default to default.

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

One view uses one component to render, so for the same route, multiple views need multiple components.

Make sure to use the components configuration correctly (with s):

const router = new VueRouter({
routes: [
  {
    path: '/',
    components: {
        default: Foo,
        a: Bar,
        b: Baz
    }
    }
  ]
});

7. Redirect

{ path: '/a', redirect: '/b' }
{ path: '/a', redirect: { name: 'foo' }}
{ path: '/a', redirect: to => {
  // 方法接收 目标路由 作为参数
  // return 重定向的 字符串路径/路径对象
}}

Note: The navigation guard is not applied to the jump route, but only to its target.

In the above example, adding a beforeEach or beforeLeave guard to the /a route has no effect.

8. Use props to decouple $route

Using $route in a component will make it highly coupled with its corresponding route, so that the component can only be used on certain URLs, limiting its flexibility.

// router文件
// 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
{
  path: '/number/:name',
  props: true,
  // 对象模式 props: { newsletterPopup: false }
  // 函数模式 props: (route) => ({ query: route.parmas.name })
  name: 'number',
  component: () => import( /* webpackChunkName: "number" */ './views/Number.vue')
}
// 组件获取
export default{
  props: ['name']
}

9. Navigation Guard

1. Three kinds of global guards

  • router.beforeEach global front guard before entering the router.
  • router.beforeResolve global resolution guard 2.5.0 is new. Called after beforeRouteEnter is called.
  • router.afterEach After the global post hook enters the router.
// 入口文件
import router from './router'
 
// 全局前置守卫
router.beforeEach((to, from, next) => {
  console.log('beforeEach 全局前置守卫');
next();
});
// 全局解析守卫
router.beforeResolve((to, from, next) => {
  console.log('beforeResolve 全局解析守卫');
next();
});
// 全局后置守卫
router.afterEach((to, from) => {
  console.log('afterEach 全局后置守卫');
});

2. Route exclusive guard

  • beforeEnter before the global front guard enters the route.
{
    path: '/number/:name',
    props: true,
    name: 'number',
    // 路由独享守卫
    beforeEnter: (to, from, next) => {
        console.log('beforeEnter 路由独享守卫');
        next();
    },
    component: () => import( /* webpackChunkName: "number" */ './views/Number.vue')
}

3. Guard inside the component

  • beforeRouteEnter
  • beforeRouteUpdate(New in 2.2)
  • beforeRouteLeave
beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
    console.log('beforeRouteEnter 组件内进入守卫');
    next();
},
beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
    console.log('beforeRouteUpdate 组件内更新守卫');
    next();
},
beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
    console.log('beforeRouteLeave 组件内离开守卫');
    next();
}
  • Component 1 jumps to Component 2, then Component 2 jumps to Component 2 itself

  • Component 1 jumps to Component 2, then Component 2 jumps to Component 1

10. The next method of the guard

next: call the method resolve hook.

  • next(): Go to the next hook in the pipeline. If all hooks are executed, the status of the navigation is confirmed.
  • next(false): Interrupt the current navigation. If the URL of the browser changes (perhaps manually by the user or the browser back button), the URL address will be reset to the address corresponding to the from route.
  • next('/') or next({ path:'/' }): Jump to a different address. The current navigation is interrupted, and then a new navigation is performed. You can pass any location object to next, and you are allowed to set options such as replace: true, name:'home', and any options used in the to prop of router-link or router.push.
  • next(error): (2.4.0+) If the parameter passed in next is an Error instance, the navigation will be terminated and the error will be passed to the callback registered by router.onError().

At last

In the end, I hope you can read the documentation more and use it in the project after you understand it, so that there will be no bugs after use, thank you.

If you find the content helpful, you can follow my official account, keep up with the latest developments, and learn together!

image.png

阅读 2.4k

大前端
学习 分享

The Best Way to Improve Yourself:

7k 声望
9.7k 粉丝
0 条评论
你知道吗?

The Best Way to Improve Yourself:

7k 声望
9.7k 粉丝
宣传栏