Vue.js - Study Note 4

Views: 1199
Wrote on April 15, 2020, 3:30 a.m.

Router

Vue-Router is a Vue.js plugin to add routing to your application. To install it, simply run:

npm install vue-router

or

yarn add vue-router

To register a router:

   let url = [
    {
      path: "/",
      name: "home",
      component: {
        template: ``
      }
    }
  ];
  let router = new VueRouter({
    routes: url
  });
  const app = new Vue({
    el: "#app",
    router: router
  });
<router-link to="/">Link</router-link>
<router-view></router-view>

In vue router normally we define one root <router-view> outlet where it renders the component which matches the defined path similarly, a rendered component can also contain it’s own, nested <router-view>.

Nested Routing / subRoute

  const router = new VueRouter({
    mode: "history",
    routes: [
      {path: '/', component: Home},
      {
        path: '/user', component: User, children: [
          //UserInfo component is rendered when /user/:id is matched
          {path: ':id', component: UserInfo, props: true}
        ]
      },
    ]
  })

Vue Router’s default mode is hash. Hash mode URLs always contain a hash symbol (#) after the hostname. The hash mode basically means our application routes will be displayed like this - http://localhost:8080/#/link. The benefit to this often lies with allowing us to have multiple client side routes without having to provide the necessary server side fallbacks. Since our application is a dead simple client-side app and we don’t want the hash in our URLs, we can get rid of it. To remove hashes in our URLs, we’ll specify the history mode property in our router instantiation:

 export const router = new VueRouter({
   mode: 'history',
   routes
 });

$route vs $router

We need to figure out the differences between route vs router.

Router

Router component is what makes the connection between browser location and the vue application. It doesn't render anything visible on your page. It just exposes API to interact with location changes of the browser. Router is the abstract for all other specific router components. Also, Router is usually a top-level component in the component tree and use only one time in the entire application.

Route

Route renders some UI when a location matches the route’s path. So an application can have many Routes based on its layout complexity in different levels of the component tree. Also, Route has some additional props to configure how the match should happen. Route internally use API provided by Router to access the location and decide whether to render the given component or not.

Let's take a look at an example:

<div id="app">
  <router-link to="/">Home</router-link>
  <router-link to="/blog">Blog</router-link>
  <router-view></router-view>
</div>
  let url = [
    {
      path: "/",
      name: "home",
      component: {
        template: `<div><h1>Home Page</h1></div>`
      }
    },
    {
      path: "/blog",
      name: "blog",
      component: {
        template: `<div><h1>Blog List</h1></div>`
      }
    }
  ];

  let router = new VueRouter({
    routes: url
  })

  const app = new Vue({
    el: "#app",
    router: router,
    mounted(){
      console.log("this.$route: ", this.$route);
      console.log("this.$router: ", this.$router);
    }
  })

So if we need to check login status for certain page, this.$route.metais a good helper/

let url = [
    {
      path: "/",
      name: "home",
      component: {
        template: `<div><h1>Home Page</h1></div>`
      }
    },
    {
      path: "/blog",
      name: "blog",
      /*****************/
      meta: {
        required_login: true
      },
      /*****************/
      component: {
        template: `<div><h1>Blog List</h1></div>`
      }
    }
  ];

  let router = new VueRouter({
    routes: url
  })

  const app = new Vue({
    el: "#app",
    router: router,
    mounted() {
      console.log("this.$route: ", this.$route);
      console.log("this.$router: ", this.$router);
      /*****************/
      // This piece of code should not
      // be set under mounted()
      // here is just an example
      // click blog then refresh the page
      // you'll see the page automatically
      // jump back to Home page.
      if (this.$route.meta.required_login) {
        this.$router.push("/")
      }
      /*****************/
    }
  })

Summary

so, as you can find out: $route is an object that include all the information of current route path; $router is a VueRouter instance object.

this.$router.push("/")
this.$router.push({name: "xxx"})

Redirect

redirect:{name: "xxx"}

Router Hooks

Vue Router only switches components for you depending on the URL. It does not handle AJAX calls to the server or role-based auth protection for example, because it’s not what it was created for, so Vue Router provides additional functionality pertaining to how routes get resolved. They are primarily used to handle error states and navigate a user seamlessly without abruptly interrupting their workflow. These hooks are also called guards.

Global Guards
  • beforeEach: action before entering any route (no access to this scope)
  • beforeResolve: action before the navigation is confirmed, but after in-component guards (same as beforeEach with this scope access)
  • afterEach: action after the route resolves (cannot affect navigation)
Per Route Guards
  • beforeEnter: action before entering a specific route (unlike global guards, this has access to this)
Component Guards
  • beforeRouteEnter: action before navigation is confirmed, and before component creation (no access to this)
  • beforeRouteUpdate: action after a new route has been called that uses the same component
  • beforeRouteLeave: action before leaving a route

Every guard function receives three arguments: - to: Route: the target Route Object being navigated to. - from: Route: the current route being navigated away from. - next: Function: this function must be called to resolve the hook. The action depends on the arguments provided to next:

  router.beforeEach(function (to, from, next){
    console.log("to", to);
    console.log("from", from);
    console.log("next", next);
    next("/") // this is similar to this.$router.push("/")
  });