Vue.js has emerged as one of the top JavaScript frameworks for building complex, reusable web components and user interfaces. With its HTML-based syntax, component-focused design, and easy integration with other libraries, Vue provides a lightweight yet powerful way to develop dynamic front-end apps.
At the core of Vue.js is a component architecture that enables encapsulated, modular UI development. Vue single-file components, with the .vue extension, unify HTML, CSS, and JavaScript within one file for each component. This eliminates the need for separate CSS files or CSS-in-JS solutions like Tailwind. Developers can view and manage all aspects of a component – template, script, and style – in one place.
As apps grow larger in scope, implementing a clear routing system is crucial for maintaining organization and navigability. Vue’s routing functionality provides a straightforward way to manage navigation between views and components. This comprehensive guide will explore the ins and outs of declarative Vue JS routing, enabling you to harness its capabilities for your next web project.
Vue offers two main APIs for structuring an application – the options API and composition API. The options API splits up component logic using separate sections like data, methods, mounted, etc. Within the <script> tag. On the other hand, the composition API, denoted by the <script setup> tag, takes a more React-like approach to component structure for a more intuitive coding experience. So developers can choose between options and composition APIs depending on their preferences for organizing component logic in Vue.
But first, let’s give the topic a little context.
Benefits and Limitations of VueJS
- Easy Learning Curve: The learning curve for VueJS is not steep. Any developer who has a general idea about how HTML CSS and JS consist of a web application altogether can easily learn VueJS.
- Gradual Adoptation: Being a progressive framework, VueJS files can be easily integrated into existing projects without the need of rewriting the whole project from the start.
- Component-Based Architecture: Since the developer can tuck each part of the component’s logic into a single file, it becomes easier do manage and debug the application.
- Vue CLI, Vue Router and VUEX: VueJS also comes with its own CLI that simplifies development. Also, by integrating essential libraries like Vue Router and VUEX, developers can craft single page web applications with dynamic routing capabilities. As we’ll explore, using Vue Router for routing and VUEX for global state management (Redux style) creates a cohesive and efficient development experience.
- Server-Side Rendering (SSR): Just like how React developers have NextJS at their disposal, for VueJS developers there’s NuxtJS when they wsh to create full-stack applications. It is useful to note that SSR is quite useful for SEO (search engine optimization) purposes.
- Big & Active Community: Developers know that when deciding to learn a language, the community that surrounds is of utmost importance. In this regard, VueJS have a big and supportive community, making it easier for non VueJS developers to get into the framework. Althıugh the VueJS community can also be regarded as a limitation if we were to compare it to the React community, which has a wider developer pool at its disposal.
If you want to know more about what the VueJS community can offer, please refer to this article to learn more about VueJS frameworks.
Limited Enterprise Adoption
While VueJS is gaining traction, still many established companies or projects prefer React or Angular as they feel they are more battle tested.
What Is Routing?
In web development, routing refers to the mechanism that allows users to navigate between different views or pages by clicking links or entering URLs. Traditional routing relies on the server to fetch fresh HTML for each page request, causing full page reloads. Modern JavaScript frameworks like Vue and React have revolutionized routing by enabling Single Page Applications (SPAs). SPAs load the full app upfront and manage navigation between views on the client side without requiring server roundtrips. This eliminates the need for full page reloads on each user action, greatly improving the experience.
Vue provides two ways to implement routing – a basic native routing approach for simple cases, and the more robust vue-router library for complex applications. In this tutorial, we’ll look at examples of both, starting with native Vue routing. To demonstrate, we’ll bootstrap a Vue app with Vite, which offers faster development through optimized builds. By the end, you’ll understand how to leverage Vue’s routing capabilities to create dynamic single-page apps.
Native Routing in Vue
While Vue doesn’t come with built-in routing, we can implement basic page navigation using its reactive properties and components.
Starting The Application
Let us start building the app by initializing Vite. If we went to a folder and wrote `npm create vite@latest`, it will first ask us what will be the name of our project. Let’s name it “my-vue-router”. Upon naming the project and pressing enter, we will be prompted with a variety of frameworks that we can use Vite to build. We will see the following choices:
Vanilla Vue React Preact Lit Svelte Solid Qwik Others
Here, we will choose Vue. In the opening section, we will specify that we want to use Javascript for the sake of the tutorial. It will almost instantly create our app. Now, we need to go into that newly created folder “my-vue-router” and run “npm install” to install the necessary packages. Once that is done, we have a working Vue application!
Now, if we run `npm run dev` to start the development server, on http://127.0.0.1:5173/ we should encounter with this page (note that the contents of the page might change depending on the Vite’s version and how they decide to create the App.vue file).
Now if you opened a separate terminal window and entered the command “code .” to open the project up in a text editor like VsCode (Notice that the dot is after the space). Now, inside the src folder, find App.vue file and delete everything in it. We will start working there.
Writing a Simple Routing
Now, in the src folder, let us create a new folder called views. We are going to put the pages that we will use routing on here. Inside of that folder, let’s create two files, Home.vue and About.vue. They will be very basic components that will specify what they are so that we can know we successfully used routing.
This is how Home.vue should look like:
<template> <div> <h1>This is Home</h1> </div> </template> <script> export default {}; </script> <style></style>
About.vue should look similar:
<template> <div> <h1>This is About</h1> </div> </template> <script> export default {}; </script> <style></style>
Now, we can go to App.vue and start writing the routing.
In the App.vue file, we start with importing the necessary dependencies for our purposes. We import ref and computed from vue, the Home and About files we’ve just created.
Now, refs are a way to reactively change the DOM (Document Object Model) in Vue, and computed properties are properties that are calculated based on the values of other data properties.
Afterward, we define a constant of routes, and a currentPath, that will check the current window location with refs. Then we add an event listener to hash change, and compute the current view.
After closing the script tag, on HTML, we define the part where we can click and change the route. The whole snippet should look like this:
<script setup> import { ref, computed } from "vue"; import Home from "./views/Home.vue"; import About from "./views/About.vue"; const routes = { "/": Home, "/about": About, }; const currentPath = ref(window.location.hash); window.addEventListener("hashchange", () => { currentPath.value = window.location.hash; }); const currentView = computed(() => { return routes[currentPath.value.slice(1) || "/"]; }); </script> <template> <a href="#/">Home</a> | <a href="#/about">About</a> | <component :is="currentView" /> </template>
That’s it! Now, if we checked the browser, we should see this page on http://127.0.0.1:5173/#/ :
And if we’d click About, the page should change to http://127.0.0.1:5173/#/about :
Routing With Vue Router
Now, even though this wasn’t too bad, it could be quite cumbersome when dealing with a larger application. Thankfully, there’s the officially supported vue router library that takes most of the complexity.
In order to start, we first need to install the npm package by running `npm install vue-router@4`. After installation, let’s go to App.vue file and once again delete everything inside it and replace its content with the following:
<template> <div> <router-link to="/">Home</router-link> <router-link to="/about">About</router-link> <RouterView /> </div> </template> <script> export default {}; </script> <style></style>
This time we do not import anything here. We have two router-links and a RouterView, which will display the contents of the pages we will route to.
Now we make a detour and go to main.js file and change its contents as such:
import { createApp } from "vue"; import { createRouter, createWebHashHistory } from "vue-router"; import App from "./App.vue"; import Home from "./views/Home.vue"; import About from "./views/About.vue"; const routes = [ { path: "/", component: Home }, { path: "/about", component: About }, ]; // Create the router instance const router = createRouter({ history: createWebHashHistory(), routes, }); const app = createApp(App); app.use(router); app.mount("#app");
Here we’re importing createRouter and createWebHashHistory from vue-router. Also instead of importing the pages Home.vue and About.vue in our App.vue file, we are importing them in here, in the main.js file. We define the routes and initiate the router with createWebHasHistory as history, and then routes. That is all. Now our application should work exactly as before. Notice how easy it is to do so now.
Vue Router Methods: Push, Replace and Go
Vue Router comes with certain methods that make the developer’s life easier. Let’s say in an application the user should be directed to another page as soon as they mount a component, or there needs to be a back button that takes the user just to the previous page.
The push() method adds a new entry to the browser’s history stack and navigate to that new route. The replace() method in turn replaces the current stack in comparison to push() method, but replaces the current one with a new entry. The go() method is used to navigate to a specific page in the history stack, for instance, when we want to navigate to the previous page, we’ll use go() method.
Now let’s change our application a bit. Let’s add a back button on the Home.vue file, and a dynamically rendering logic on About.Vue, that’ll navigate the user to a new view called MyView.vue we will create in a second as soon as About component mounts.
Let’s start with adding the back button to the Home page. Go to Home.vue file and change its content as such :
<template> <div> <h1>This is Home</h1> <button @click="goBack">Go Back</button> </div> </template> <script> export default { methods: { goBack() { this.$router.go(-1); }, }, }; </script> <style></style>
This example uses Vue’s options API, which was the standard way of writing Vue apps for a long time. We have a button with a @click handler that calls the goBack() method defined in the script’s methods section. goBack() calls the go() method with -1 as the argument – similar to accessing the last element in an array, this allows us to navigate back one page.
This is how the Home page should look like now:
So on the Home page, the “Go Back” button will now take us to the previous page we visited.
Let’s add more functionality – say we want to redirect users to a new page when they visit About. First, create a MyView.vue component in /views, like so:
<template> <div> <h1>This is MyView</h1> </div> </template> <script> export default {}; </script> <style></style>
The MyView.vue component we created only contains a simple template for now saying “This is the My View page”.
Before we update About.vue to redirect to MyView, we need to configure MyView in main.js. This is our new main.js file with the updated import and name keyword added:
import { createApp } from "vue"; import { createRouter, createWebHashHistory } from "vue-router"; import App from "./App.vue"; import Home from "./views/Home.vue"; import About from "./views/About.vue"; import MyView from "./views/MyView.vue"; const routes = [ { path: "/", component: Home }, { path: "/about", component: About }, { path: "/myview", component: MyView, name: "MyView" }, ]; // Create the router instance const router = createRouter({ history: createWebHashHistory(), routes, }); const app = createApp(App); app.use(router); app.mount("#app");
As you can see, we added a name keyword “MyView” when defining the MyView route in main.js:
` { path: “/myview”, component: MyView, name: “MyView” },`, we will use this name as a reference when we want to dynamically navigate the user from a page to another.
Let’s go back to About.vue and change its contents like this:
<template> <div> <h1>This is About</h1> </div> </template> <script> export default { mounted() { this.$router.push({ name: "MyView" }); }, }; </script> <style></style>
The mounted() hook runs when the component is fully loaded. So here, we use it to push the router to the “MyView” named route.
By referencing “MyView”, Vue Router knows to navigate to that component, instead of showing About. So now when a user clicks “About”, they will see the MyView page render instead.
This demonstrates how named routes allow flexible mapping between components and routes in Vue Router. We are able to redirect to MyView dynamically without hardcoding the route.
Conclusion
In this tutorial, we explored VueJS routing in depth. First, we used Vue’s native routing capabilities by directly importing Vue and configuring routes. Then, we upgraded to the more robust vue-router module for complex applications.
The vue-router library is invaluable when dealing with intricate routing needs and building extensive single page applications. It provides powerful tools like dynamic route mapping and programmatic navigation that take your routing to the next level.
Now, armed with a solid understanding of Vue routing, you are well-prepared to build navigation-driven applications that deliver exceptional user experiences, akin to the standards expected in top-tier Vue development services.
If you enjoyed this, be sure to check out our other Vue articles.
- Angular, React, or Vue.Js for My Web App?
- My Experience With Vue 3
- Streamline Your Design with Nuxt and Tailwind
- Harnessing Vue $Emit for Effective Event Handling
- Best Vue UI Frameworks & Component Libraries
FAQ
What is the difference between VueJS and Vue Router?
Vue.js is a framework for building modern single-page applications (SPAs), similar to React or Angular. It provides capabilities like a virtual DOM, two-way data binding, lifecycle methods, and modular components to simplify complex UIs.
Vue Router is a companion library that makes routing and navigation easy in Vue apps. While Vue.js is the overarching framework, Vue Router specifically handles navigation tasks like push(), go(), and replace() for page transitions.
So in summary:
- Vue.js – The core framework for building reactive SPAs
- Vue Router – A plugin for handling routing and navigation in Vue apps
To make Vue Router available globally, you would typically export the router instance, allowing access across the app’s components. Together Vue.js and Vue Router provide a robust framework for crafting navigable single page applications.
What are the differences between Hash Mode and History Mode in Vue Router?
The key difference between Hash and History mode in Vue Router is how the URL is formatted.
Hash mode adds a hash # symbol to the URL after the base, like http://site.com/#/page. The hash content isn’t sent to the server, so routing is handled client-side by Vue. However, the hash can potentially hurt SEO.
History mode uses cleaner, conventional URLs like http://site.com/page by leveraging the HTML5 History API to manipulate the browser history. This is better for SEO, but requires server-side configuration to handle URL rewrites and may not work in all environments.
How does route guard work in Vue Router?
There are some route guards that can protect the routes of your VueJS project. For example, you can use the beforeEnter route guard to perform logic before navigating to the route. Find authenticated users, redirect unauthenticated users to a different login page, etc.
For example, from a hypothetical point of view, you can imagine the following situation: We have a page that we want to protect and for that matter, we use in component beforeRouteEnter method do check for authenticated users, if not, we redirect them to the login page.
<template> <div> <h1>Welcome to the Protected Page!</h1> </div> </template> <script> export default { beforeRouteEnter(to, from, next) { const isAuthenticated = checkIfUserIsAuthenticated(); if (isAuthenticated) { next(); } else { next({ name: 'login' }); } }, }; </script> <style> </style>
As you can see, beforeRouteEnter method checks the user’s authentication with an hypothetical checkIfUserIsAuthenticated() function and reveals the page only if they are authenticated. If not, they need to go to login page and sign in.