In this comprehensive guide, we will walk you through creating a Vue project and setting up Vue Router for navigation between different pages using the new Composition API with <script setup>
. We’ll include modern CSS design for all components, detailed code explanations, error handling, and form validation to ensure you have all the knowledge you need to build a robust Vue application.
Step 1: Create a New Vue Project
First, let’s create a new Vue project using Vue CLI. Open your terminal and run the following commands:
vue create myapp
cd myapp
These commands create a new directory named myapp
and navigate into it.
Explanation:
vue create myapp
: This command initializes a new Vue project named “myapp”.cd myapp
: This command changes the directory to the newly created project folder.
Step 2: Start Your App
To start your newly created app, run:
npm run serve
Your app should now be running, and you can view it in your browser at http://localhost:8080
.
Explanation:
npm run serve
: This command compiles and hot-reloads your app for development. It also starts a development server.
Step 3: Add Vue Router
Next, we need to add Vue Router to our project. Run the following command:
vue add router
Follow the prompts to set up the router. This will create a new file src/router/index.js
where we will define our routes.
Explanation:
vue add router
: This command installs the Vue Router plugin and sets up basic routing for your project.
Step 4: Configure Vue Router
Open src/router/index.js
and update it as follows:
// Import necessary functions from Vue Router
import { createRouter, createWebHistory } from 'vue-router'
// Import the components that will be used as views
import Home from '../views/Home.vue'
import Profile from '../views/Profile.vue'
import Product from '../views/Product.vue'
import About from '../views/About.vue'
// Define the routes for the application
const routes = [
{
path: '/',
name: 'Home',
component: Home // Map the Home component to the root path
},
{
path: '/profile',
name: 'Profile',
component: Profile, // Map the Profile component to the /profile path
},
{
path: '/product/:id',
component: Product // Dynamic route matching with product ID
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') // Lazy-load the About component
}
]
// Create and configure the router instance
const router = createRouter({
history: createWebHistory(process.env.BASE_URL), // Use HTML5 history mode
routes // Pass the routes defined above
})
// Export the router to be used in the main.js file
export default router
Explanation:
import { createRouter, createWebHistory } from 'vue-router'
: Import the necessary functions from Vue Router.import Home from '../views/Home.vue'
: Import the Home component from the specified path.const routes = []
: Define an array of route objects.component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
: Lazy-load the About component to improve performance.const router = createRouter({})
: Create a new router instance.history: createWebHistory(process.env.BASE_URL)
: Use HTML5 history mode for navigation.export default router
: Export the router instance for use in the application.
Step 5: Update Your App Component
Next, we need to update our main application component to include navigation links and a router view. Open src/App.vue
and modify it as follows:
<template>
<div id="nav">
<!-- Navigation links to different routes -->
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link :to="{ name: 'Profile', params: { username: 'cairocoders' } }">Profile</router-link> |
<router-link to="/product/123">Product</router-link>
</div>
<!-- This is where the matched component will be rendered -->
<router-view/>
</template>
<script setup>
</script>
<style scoped>
#nav {
font-family: Arial, sans-serif;
margin: 20px;
}
router-link {
margin-right: 10px;
text-decoration: none;
color: #42b983;
}
router-link:hover {
color: #35495e;
}
</style>
Explanation:
<router-link to="/">Home</router-link>
: Creates a link to the Home route.<router-view/>
: Placeholder where the matched component will be rendered.- CSS: Adds styles to navigation links.
Step 6: Initialize the Router in Main.js
Open src/main.js
and update it to use the router:
// Import necessary modules
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// Create and mount the app instance, using the router
createApp(App).use(router).mount('#app')
Explanation:
import { createApp } from 'vue'
: Import the function to create a Vue application.import App from './App.vue'
: Import the main App component.import router from './router'
: Import the router configuration.createApp(App).use(router).mount('#app')
: Create and mount the app instance, using the router.
Step 7: Create View Components
Create the view components for Product
and Profile
.
Product View
Create src/views/Product.vue
and add the following code:
<template>
<div class="product">
<!-- Display the Product Page header -->
Product Page
</div>
<span>
<!-- Display the dynamic product ID from the route parameters -->
Looking for Product: {{ $route.params.id }}
</span>
</template>
<script setup>
</script>
<style scoped>
.product {
font-family: Arial, sans-serif;
margin: 20px;
color: #333;
}
span {
font-size: 1.2em;
color: #555;
}
</style>
Explanation:
{{ $route.params.id }}
: Accesses the dynamic route parameter for the product ID.- CSS: Adds styles for the product view.
Profile View
Create src/views/Profile.vue
and add the following code:
<template>
<div class="profile">
<!-- Display the Profile Info header -->
Profile Info
</div>
<span>
<!-- Display the dynamic username from the route parameters -->
{{ $route.params.username }}
</span>
</template>
<script setup>
</script>
<style scoped>
.profile {
font-family: Arial, sans-serif;
margin: 20px;
color: #333;
}
span {
font-size: 1.2em;
color: #555;
}
</style>
Explanation:
{{ $route.params.username }}
: Accesses the dynamic route parameter for the username.- CSS: Adds styles for the profile view.
Error Handling and Form Validation
Error handling and form validation are crucial for creating a robust application. Here’s how you can implement them.
Error Handling in Vue Router
You can catch navigation errors using router hooks.
router.beforeEach((to, from, next) => {
try {
next()
} catch (error) {
console.error('Navigation Error:', error)
next(false) // Cancel the navigation
}
})
Explanation:
router.beforeEach()
: A global guard that executes before each navigation.next(false)
: Cancels the navigation if there’s an error.
Form Validation
Let’s create a simple form with validation.
Create src/views/Form.vue
:
<template>
<div>
<h2>Form Validation</h2>
<form @submit.prevent="validateForm">
<div>
<label for="name">Name:</label>
<input type="text" v-model="name" id="name" />
<span v-if="errors.name">{{ errors.name }}</span>
</div>
<div>
<label for="email">Email:</label>
<input type="email" v-model="email" id="email" />
<span v-if="errors.email">{{ errors.email }}</span>
</div>
<button type="submit">Submit</button>
</form>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const formState = reactive({
name: '',
email: '',
errors: {}
})
function validateForm() {
formState.errors = {}
if (!formState.name) {
formState.errors.name = 'Name is required.'
}
if (!formState.email) {
formState.errors.email = 'Email is required.'
} else if (!validEmail(formState.email)) {
formState.errors.email = 'Invalid email format.'
}
if (!Object.keys(formState.errors).length) {
// Form is valid, proceed with submission
console.log('Form Submitted', { name: formState.name, email: formState.email })
}
}
function validEmail(email) {
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@(([^<>()[\]\.,;:\s@"]+\.)+[^<>()[\]\.,;:\s@"]{2,})$/i
return re.test(email)
}
</script>
<style scoped>
h2 {
font-family: Arial, sans-serif;
}
form {
display: flex;
flex-direction: column;
max-width: 400px;
margin: auto;
}
div {
margin-bottom: 10px;
}
label {
font-weight: bold;
}
input {
padding: 5px;
font-size: 1em;
}
span {
color: red;
font-size: 0.9em;
}
button {
padding: 10px;
font-size: 1em;
background-color: #42b983;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #35495e;
}
</style>
Explanation:
v-model="formState.name"
: Binds the input field to the reactive state property.validateForm()
: Validates the form fields and displays error messages.- CSS: Adds styles for the form and validation messages.
Welcome to DevTechTutor.com, your ultimate resource for mastering web development and technology! Whether you're a beginner eager to dive into coding or an experienced developer looking to sharpen your skills, DevTechTutor.com is here to guide you every step of the way. Our mission is to make learning web development accessible, engaging, and effective.