Vue Router 4–404 and Nested Routes
Tags: vue, webdev, programming, javascript
Published: 2021-01-25 23:25:55

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


**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.