This is the 20th day of my participation in the More text Challenge. For more details, see more text Challenge

introduce

In a project that uses vue-Router, instantiate VueRouter with its configuration option routes, which specifies the relationship between the route and the component of the view or between the route and other routes. The Router configuration option is the most important configuration.

Object properties in routes

interface RouteConfig = {
  path: string, component? : Component, name? : string,// Name the route*components? : { [name: string]: Component },// Name the view component https://router.vuejs.org/zh/guide/essentials/named-views.html#%E5%B5%8C%E5%A5%97%E5%91%BD%E5%90%8D%E8%A7%86%E5%9B%BEredirect? : string | Location |Function, props? : boolean |Object | Function, alias? : string |Array<string>, children? :Array<RouteConfig>, // Set set bybeforeEnter? :(to: Route, from: Route, next: Function) = > void, *meta? : any,/ / server +*caseSensitive? : boolean,// Is the matching rule case-sensitive? (Default: false)*pathToRegexpOptions? :Object // Options for compiling regex
}
Copy the code

path: string

When the browser URL matches the path, router-view renders the current route object

const routes = [
    {
      path'/'.component: Home
    },
    {
      path:'/user'.component: User
    }
  ]
  
  const router = new VueRouter({
    routes
  })
Copy the code

Note that Vue’s router supports dynamic paths in the form “/: attribute name “as part of the current path string. This string route is used as a dynamic route to match the response string information on the real URL

const routes = [
    {
      path'/'.component: Home
    },
    {
      path:'/user/:id/:local'.// Dynamic path: ID :local
      component: User
    }
]
  
const router = new VueRouter({
    routes,
})
// Route jump

<div id="app">
    <router-view  />
    // The following links will match /user/:id/:local
    <router-link  to="/user/007/lk">The user 007</router-link>
    <router-link  to="/user/111/js">The user 111</router-link>
    <router-link  to="/user/10086/yk">The user 10086</router-link>
    <router-link  to="/user/241247/la">The user 241247</router-link>
</div>
$route.params (); /* When we jump to the route above, the routing view component User can get the dynamic path matching information from this.$route.params url /user/007/lk this.$route.params -> {id:'007',local:'lk'} url /user/10086/yk this.$route.params -> {id:'10086',local:'yk'} */
Copy the code

Note that this.$route is the information object for the current vUE application route

// http://localhost:8080/#/user/10086/cc? wd=iPhone&aa=test
{
    name: undefined.// The name of the current route
    *fullPath: "/user/10086/cc" // The full path of the current URL
    *hash: "" // Hash of the current route* * matched: [{...}] meta: {}params: {id"10086".local"cc"} // The dynamic path matches the key-value pair object
    *path: "/user/10086/cc" // The current URL matches the path
    query: { // Query string url? The following parameters are resolved by the object
        wd"iPhone".aa"test"}}Copy the code

Component: a component | () = > import (components)

The routing component rendered when the current browser URL matches the path of the route

import Vue from 'vue'
import HotMusicList from '.. /views/HotMusicList'

const routes = [
  {
    path'/hot'.component: HotMusicList
  },
  {
    // Get a different id for each song
    path'/music/:id'.// Route lazy loading, in the form of functions, can be used to load the project which is not allowed to be loaded at the beginning of the project
    // The route component is loaded into the project only when the browser jumps to the current route
    // The advantage of doing this is to reduce unnecessary load and reduce application loading speed and running bandwidth
    component() = > import('.. /views/MusicPlay')}]Copy the code

Note use lazy loading for routing components that do not need to be loaded at the beginning of the project

name: string

Name the route and make it a named route. The navigation of the route can be skipped using name. (Only the named route can accept pramas directly when the route is navigated using location)

const routes = [
  {
    path'/user'.name'User'.component() = > import('.. /views/User.vue')}]Copy the code

Redirect: string | Location | Function

Redirect route. When the current application access navigates to this route, the route is automatically redirected to the new route specified by the redirect

const routes = [
  {
    path'/contact'.component: ContactView
  },
  {
    path'/user/:id'.name'User'.component() = > import('.. /views/User.vue')}, {path'/oldpath1'.redirect'/contact'
  },
  {
    path'/oldpath2'.redirect: { name'User'.params: { name'Ming'.age19}}},The redirect function must return either the redirect route's path or location */
  {
    path'/oldpath2'.redirect:(oldpathLocation) = > '/contact'
  }
  {
    path'/oldpath4'.redirect:(oldpathLocation) = > { name'User'.params: { name'Ming'.age19}}}]Copy the code

props: boolean | Object | Function

Generally, only this.$route.params can be used to obtain the dynamically matched value. When the props attribute is set, the dynamically matched key-value pair can be passed directly to the view component as the component props, which greatly reduces the coupling Boolean value of the component. If the props attribute is set to true, all key/value pairs of rout. params will be set to the component props attribute.

const routes = [
  {
    path'/hot'.component: HotMusicList
  },
  {
    // Get a different id for each song
    path'/music/:id'.// Lazy route loading
    component() = > import('.. /views/MusicPlay'), 
    propstrue}]// The component can internally access this.$route.id with props ID
<template>
  <div>The songs<audio controls :src="musicUrl"/>
  </div>
</template>

<script>

export default {
  props: ['id'].// The routing dynamic path matches the props of the current component
  data() {
      return {
          musicUrl' '}},created() {
    fetch(`/song/url? id=The ${this.id}`)
      .then((res) = > res.json())
      .then(({ data }) = > {
          // In real development, this is to determine whether the data request was successful
        console.log(data[0]);
          // Assign the song data to data
        this.musicUrl = data[0]? .url }); }};</script>
Copy the code

The object props form is the object key as the props property name of the rendering component, and the value is the corresponding attribute value (value does not change this way of writing, so we always pass props as static properties).

{
    path'/home/:id'.name'Home'.props: {
        a: 1.bfalse
    },
    component: Home
}
Copy the code

The function writing of the function props takes the current routing information object as an argument. The function returns an object. The key of the object is the props attribute of the rendering component, and the value is the corresponding attribute value

{
    path'/home/:id'.name'Home'.props(route) = > ({
        a: route.query.wd, // Pass the route query.wd to the component Home props
        b: route.params.id // Pass the route params.id to the component's B props
    }),
    component: Home
}
Copy the code

alias: string| Array[string]

Alias of a route. Multiple paths can be assigned to a route. The same routing component is accessed when these alias paths are accessed

const routes = [
  {
    path'/hot'.component: HotMusicList,
    alias: ['/list'.'/rank'.'recommend']}]Copy the code

children? : Array[RouteConfig]

The embedded route allows you to set a secondary route for the current route

[{path'/home'.component: Home,
    children: [{path'/home/follow'.component() = > import('.. /views/home/Follow')}, {path'recommend'.// recommed: // recommed /recommed
        component() = > import('.. /views/home/Recommend')}]}]Copy the code

beforeEnter: (to: Route, from: Route, next: Function) => void

When the application is about to navigate to the current route, this guard can be used to perform some logical operations to determine whether to block the navigation

Instance method of Router

When the concept configures a VueRouter instance into Vue, the Vue instance will have a this.$router property, which is the current instance of VueRouter. It provides all the apis for programmatic navigation.

Note that router is a route instance object containing the route property method,router is a route instance object containing the route property method,route is the current browsing access URL routing confidence object

*VueRouter instance property

  • The app configures the Vue root instance of the current router

  • Mode current Router using the pattern of “hash” | “history”

  • CurrentRoute route information object corresponding to the currentRoute

VueRouter instance method

router.push(string | location)

Programmatically navigates to the specified route

<template>
  <div>
    <h3>The home page</h3>
    <div class="tab">
      <router-link to="/home/follow">Focus on</router-link>|
      <button @click="gotoRecommend">recommended</button>
    </div>
    <router-view />
  </div>
</template>

<script>
export default {
  methods: {
    gotoRecommend() {
      // this.$router.push("/home/recommend");
      this.$router.push({path:"/home/recommend".query: {wd:1.offset:0}})},}};</script>     
Copy the code

router.replace(string | location)

Replace the current route programmatically to navigate to a new route

<template>
  <div>
    <h3>The home page</h3>
    <div class="tab">
      <router-link to="/home/follow">Focus on</router-link>|
      <button @click="gotoRecommend">recommended</button>
    </div>
    <router-view />
  </div>
</template>

<script>
export default {
  methods: {
    gotoRecommend() {
      // this.$router.replace("/home/recommend");
      this.$router.replace({path:"/home/recommend".query: {wd:1.offset:0}})},}};</script>    
Copy the code

router.go(Int number)

The program moves the number bar forward and backward from the current route history stack

this.$router.go(3)   // Advance 3 entries from the current route history stack
this.$router.go(-1) // Move back one line from the current route history stack
this.$router.go(0)  // Force the page refresh
Copy the code

Note that when the current forward/back number is larger than the length of the history stack of the instance route, the route will move forward to the last one or back to the first one, but this is not recommended because it can cause performance problems and cause page stalling

router.back()

The program moves back 1 bar from the current route history stack

this.$router.back() $router.go(); $router.go();
Copy the code

router.forward()

The program advances 1 bar from the current route history stack

this.$router.forward() // equivalent to this.$router.go(1)
Copy the code

The route was loaded lazily. Procedure

When using vue.js to write a single page application, the packaged JavaScript package will be very large, which will affect the page loading. We can optimize this problem by taking advantage of lazy route loading. When we use a certain route, we will load the corresponding component, which will be more efficient.

Lazy loading is not used

The component is introduced first, and it’s loaded in advance. And then it’s there whether it’s used or not

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '.. /views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/'.name: 'Home'.component: Home
  },
]

const router = new VueRouter({
  routes
})

export default router
Copy the code

Using lazy loading

The component is loaded only when the route is used

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/mock'.name: 'Mock'.// route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () = > import(/* webpackChunkName: "about" */ '.. /views/Mock.vue')}]const router = new VueRouter({
  routes
})

export default router
Copy the code

History mode and hash mode

Vue-router default hash mode — Uses the URL hash to simulate a full URL, so that the page does not reload when the URL changes.

If we don’t want an ugly hash, we can use the History mode of the route, which makes full use of the History. pushState API to redirect the URL without having to reload the page.

The history mode

History — Takes advantage of the new pushState() and replaceState() methods in the HTML5 History Interface. (Requires browser-specific support.) These two methods apply to the browser’s history stack and provide the ability to modify the history on top of the existing back, forward, and go methods (which can be viewed in the Router instance method). It’s just that when they make a change, the browser doesn’t immediately send a request to the back end even though the current URL has been changed.

manually

The effect

Hash pattern

Hash — the # symbol in the URL of the address bar (this hash is not a cryptographic hash). For example, the URL: http://localhost:8081/#/form has a hash value of #/form. The feature is that the hash appears in the URL but is not included in the HTTP request and has no effect on the back end, so changing the hash does not reload the page.

Routing guard

Global Route guard

  • Router. beforeEach Front guard

  • * Router. BeforeResolve front guard

  • * Router. AfterEach Rear guard

Is a

In projects developed with vue-Router, switching between different routes usually unloads the outgoing routing component and mounts the incoming routing component.

In this case, we can perform some logical operations on the page through the declaration cycle of vue. However, in cases where the application reduces the frequency of uninstallation to improve the user experience or save the activity of the exiting component, the routing switch after wrapping the router-view with the keep-alive component will remove the exiting component. At this point, if your component needs to do something to modify the component’s own data DOM programming as the route enters or leaves, you can no longer rely on the vUE lifecycle. In this case, use the routing guard within the component.

  • BeforeRouteEnter The routing component is about to enter

  • BeforeRouteUpdate (added in 2.2) Routing component to be updated -> /music/10086 /music/10010

  • The beforeRouteLeave routing component is about to leave

export default {
  props: ['id'].data() {
      return {
          musicUrl' '
      }
  },

  beforeRouteEnter (to, from, next) {
    // Called before the rendering component's corresponding route is confirmed
    / / no! Can!!!! Get component instance 'this'
    // Because the component instance was not created before the guard executed
    console.log(undefined)
  },
  beforeRouteUpdate (to, from, next) {
    // called when the current route has changed but the component is being reused
    // For example, for a path with dynamic parameters /foo/:id, jump between /foo/1 and /foo/2,
    // Since the same Foo component is rendered, component instances are reused. The hook will be called in that case.
    // Can access component instance 'this'
  },
  beforeRouteLeave (to, from, next) {
    // called when navigating away from the corresponding route of the component
    // Can access component instance 'this'}}Copy the code

Note that component-specific route guard methods all contain three arguments to from next

  • to : locationThe target route information object of this route navigation
  • from : locationWhich route information object to jump from in this route navigation ()
  • next : functionWhether this method allows the route jump
next()  // Allow route hops
next(true) // Allow route hops
next(false) // Route hops are not allowed
next('/') / next({ path: '/' }) // Jump to a different address. The current navigation is interrupted and a new navigation is made. You can pass any location object to next and allow options such as replace: true and name: 'home' to be set.
// Note that only the next method of beforeRouteEnter can accept a callback function,
// The callback function takes the current routing component instance object as a parameter, with which we can manipulate the current component
beforeRouteEnter(to, from, next) {
    console.log(to , from)
    console.log('Component is about to enter, this is component instance does not yet exist'.this)
    next(vm= > {
      fetch(`/song/url? id=${vm.id}`)
      .then((res) = > res.json())
      .then(({ data }) = > {
          // In real development, this is to determine whether the data request was successful
        console.log(data[0]);
          // Assign the song data to data
        vm.musicUrl = data[0]? .url }); })// Allow route hops
}
Copy the code

Case 2

In projects developed with vue-Router, switching between different routes usually unloads the outgoing routing component and mounts the incoming routing component.

In this case, we can perform some logical operations on the page through the declaration cycle of vue. However, if there are cases where the application can reduce the frequency of uninstallation to improve user experience or save the activity of the exiting component, the switch after wrapping the router-view with the keep-alive component will uninstall the exiting component. In this case, If your component needs to do something when the route enters or leaves, you don’t need to change the state of the component, you just need to determine whether the route is allowed to jump, etc. In this case, use route exclusive guards.

BeforeEnter (to, from, next) Is triggered when a route is about to navigate to the current route

const router = new VueRouter({
  routes: [{path: '/foo'.component: Foo,
      beforeEnter: (to, from, next) = > {
        // ...}}}])Copy the code

Log in to verify the configuration of route exclusive guard

const routes = [
    {
        path'/'.component: Home
    },
    {
        path'/discover'.component() = > import('.. /views/Discover')}, {path'/mine'.component() = > import('.. /views/Mine'),
        // Route exclusive guard
        beforeEnter(to, from, next) {
            // Because the guard does not do any DOM operations or read or write to the component's own state
            // Such a guard can be used as the route exclusive guard
            // The correct method exists in the cookie storage
            if (localStorage.getItem("user")) {
              next();
            } else {
              Next receives a callback function and jumps in the callback function
              // This may cause some unnecessary bugs. // This may cause some unnecessary bugs
              // next((vm) => {
              // vm.$router.replace('/landr')
              / /});
              next({name:'login'.params:{to}}); // Block the jump and navigate directly to the specified route}}}, {path'/landr'.// login an register
        component() = > import('.. /views/loginanregister/LoginAndRegister'),
        children: [{name:'login'.path'login'.component() = > import('.. /views/loginanregister/Login')}, {path'register'.component() = > import('.. /views/loginanregister/Register')}]}]Copy the code

Is three

The global route guard is used when there are multiple routes in the application that require the same logical route guard judgment, and the logical operation does not require direct manipulation of component DOM or component state. (The most common application of the global route guard is login authentication.)

BeforeEach (to, From,next) Global front guard

import Vue from 'vue'
import Router from 'vue-router'
import Home from '.. /views/Home'

Vue.use(Router)

const routes = [
    {
        path'/'.name'Home'.component: Home
    },
    {
        path'/discover'.name'Discover'.component() = > import('.. /views/Discover')}, {path'/mine'.name'Mine'.component() = > import('.. /views/Mine'),}, {path'/landr'.// login an register
        component() = > import('.. /views/loginanregister/LoginAndRegister'),
        children: [{name'login'.path'login'.component() = > import('.. /views/loginanregister/Login')}, {path'register'.component() = > import('.. /views/loginanregister/Register')}]}]const router = new Router({
    routes,
    linkExactActiveClass'active'
})
// The global guard of the route is called for all route hops
// The global Route guard is also the most suitable place for login authentication in Vue Router applications
router.beforeEach((to, from, next) = > {

    if(to.name === "Mine" || to.name === "Discover") {
        // Because the guard does not do any DOM operations or read or write to the component's own state
        // Such a guard can be used as the route exclusive guard
        // The correct method exists in the cookie storage
        if (localStorage.getItem("user")) {
            next();
        } else {
            Next receives a callback function and jumps in the callback function
            // This may cause some unnecessary bugs. // This may cause some unnecessary bugs
            // next((vm) => {
            // vm.$router.replace('/landr')
            / /});
            next({ name'login'.params: { to } }); // Block the jump and navigate directly to the specified route}}else {
        next()
    }

})

export default router
Copy the code

Router. beforeResolve(to, From,next) Global front guard, after beforeEach triggers

Router.aftereach (to, From) Global rear guard, which is triggered when the guard route has left. The guard has no next, and the next function does not change the navigation itself