Categories
Vue 3

Vue Router 4–404 and Nested Routes

Spread the love

Vue Router 4 is in beta and it’s subject to change.

To build a single page app easily, we got to add routing so that URLs will be mapped to components that are rendered.

In this article, we’ll look at how to use Vue Router 4 with Vue 3.

Catch-All / 404 Not Found Route

We can create a catch-all or 404 route by using the asterisk pattern as the path.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <p>
        <router-link to="/foo">Foo</router-link>
      </p>
      <router-view></router-view>
    </div>
    <script>
      const Foo = {
        template: "<div>foo</div>"
      };

      const NotFound = {
        template: "<div>not found</div>"
      };

      const routes = [
        { path: "/foo", component: Foo },
        { path: "/:catchAll(.*)", component: NotFound }
      ];

      const router = VueRouter.createRouter({
        history: VueRouter.createWebHistory(),
        routes
      });

      const app = Vue.createApp({});
      app.use(router);
      app.mount("#app");
    </script>
  </body>
</html>

We define a catch-all route with the /:catchAll(.*) capture group instead of * as in Vue Router 3.

Now when we go to any path that isn’t foo , we’ll see the ‘not found’ message.

Nested Routes

We can create nested routes with the children property.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <p>
        <router-link to="/parent/home">parent</router-link>
      </p>
      <router-view></router-view>
    </div>
    <script>
      const Parent = {
        template: `<div>
          parent
          <router-view></router-view>
        </div>`
      };

      const Home = {
        template: `<div>home</div>`
      };

       const routes = [
        {
          path: "/parent",
          component: Parent,
          children: [{ path: "home", component: Home }]
        }
      ];

      const router = VueRouter.createRouter({
        history: VueRouter.createWebHistory(),
        routes
      });

      const app = Vue.createApp({
        watch: {
          $route() {
            console.log(this.$route.resolve);
          }
        }
      });
      app.use(router);
      app.mount("#app");
    </script>
  </body>
</html>

We have a routes array with an object that has the children property.

The property has an object with the path and component properties like a regular route.

In the router-link , the to prop has the path to the nested route.

The Parent component has the router-view component so that we can view the content of the child route.

Therefore, when we click on the parent link, we see the:

parent
home

text displayed.

We can have URL parameters in the parent route.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <p>
        <router-link to="/parent/1/home">parent</router-link>
      </p>
      <router-view></router-view>
    </div>
    <script>
      const Parent = {
        template: `<div>
          <div>parent {{ $router.currentRoute.value.params.id }}</div>
          <div><router-view></router-view></div>
        </div>`
      };

      const Home = {
        template: `<div>home</div>`
      };

      const routes = [
        {
          path: "/parent/:id",
          component: Parent,
          children: [{ path: "home", component: Home }]
        }
      ];

      const router = VueRouter.createRouter({
        history: VueRouter.createWebHistory(),
        routes
      });

      const app = Vue.createApp({
        watch: {
          $route() {
            console.log(this.$route.resolve);
          }
        }
      });
      app.use(router);
      app.mount("#app");
    </script>
  </body>
</html>

To add the :id URL parameter placeholder.

Since the router-link ‘s to prop is now /parent/1/home and we have the $router.currentRoute.value.params.id in the Parent ‘s template, we’ll see the number 1 displayed.

The URL parameter placeholder of the parent stays with the parent.

Conclusion

The way we define 404 and nested routes are slightly different from Vue Router 3 in Vue Router 4.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *