Advanced apps with Vue CLI
Vue CLI (Command Line Interface) is a full system for rapid Vue.js development.
#installing Vue CLI
npm install -g @vue/cli
#creating a project scaffold
vue create my-project
# OR using the Graphical User Interface
vue ui
You can manually select what packages or features to be installed, options that are likely needed for more production-oriented projects.

Adding plugins to the project.
vue add eslint
Single File Components
When a project is created, a structured folder hierarchy is created.
Also Single File Components are in place (with the .vue extension), meaning we'll be able to access the logic, the layout and the style within the same file.
What About the Separation of Concerns?
One important thing to note is that separation of concerns is not equal to the separation of file types. In modern UI development, instead of dividing the codebase into three huge layers that interweave with one another, it makes much more sense to divide them into loosely-coupled components and compose them. Inside a component, its template, logic and styles are inherently coupled, and collocating them actually makes the component more cohesive and maintainable.
<template>
<div>
<h1>My Single Page Component</h1>
<img :src="imageUrl" alt="My Image">
</div>
</template>
<script>
export default {
name: 'MySinglePageComponent',
data() {
return {
imageUrl: 'https://example.com/my-image.png',
};
},
};
</script>
<style>
img {
width: 100%;
height: auto;
}
</style>
<template>
<div>
<my-single-page-component></my-single-page-component>
</div>
</template>
<script>
import MySinglePageComponent from './MySinglePageComponent.vue';
export default {
components: {
MySinglePageComponent,
},
};
</script>
In Vue.js, a view is a component.
There's no fundamental difference between a "view" and a "component" in terms of how Vue.js treats them. Both are built using the same component structure (with a template, script, and optional style).
So, why the distinction?
The distinction between "views" and "components" is primarily a matter of convention and organization within a Vue.js project. It's a way to structure your code and make it easier to understand.
Here's how the convention usually works:
Components: These are generally smaller, reusable UI elements that can be used across multiple parts of your application. Think of things like buttons, input fields, modals, or lists. They often focus on a specific piece of functionality or visual element.
Views: These are typically the top-level components that represent different "pages" or "screens" in your application. They are usually associated with specific routes and are responsible for composing and displaying multiple components to create the overall layout of a page.
Example:
Imagine an e-commerce application:
Components:
ProductCard.vue
,ShoppingCart.vue
,AddToCartButton.vue
Views:
HomePage.vue
,ProductDetailsPage.vue
,CheckoutPage.vue
Folder Structure
To reinforce this convention, Vue.js projects often have separate folders:
src/components/
: For reusable components.src/views/
: For top-level view components.
Important Notes
Flexibility: This is just a convention, not a strict rule. You can structure your project in a way that makes sense to you.
Router Views: Vue Router (the official routing library for Vue.js) uses a special component called
<router-view>
to dynamically display the component associated with the current route. This is where your "view" components are typically rendered.
Practical example: Making HTTP requests
We can use the default fetch
API or we can use a popular library such as Axios.
// First we need to install the Axios as a Vue CLI Plugin
vue add axios
// or
npm install axios
This Vue component, named AxiosExample
, fetches a list of posts from the JSONPlaceholder API upon mounting. It uses Axios to make an asynchronous GET request and manages three states in its template: "Loading data..." while the request is in progress, "Error fetching data..." if the request fails, and a list of post titles and bodies if the request is successful. The component updates its posts, loading, and error data properties to control which state is displayed to the user, ensuring a clear and informative UI during the data fetching process.
<template>
<div>
<h1>Fetching Data with Axios in Vue</h1>
<div v-if="loading">
Loading data...
</div>
<div v-else-if="error">
Error fetching data: {{ error }}
</div>
<div v-else>
<h2>Posts from JSONPlaceholder API</h2>
<ul>
<li v-for="post in posts" :key="post.id">
<h3>{{ post.title }}</h3>
<p>{{ post.body }}</p>
</li>
</ul>
</div>
</div>
</template>
<script>
// 1. Import Axios
import axios from 'axios';
export default {
name: 'AxiosExample',
data() {
return {
posts: [],
loading: false,
error: null,
};
},
mounted() {
this.fetchPosts(); // Call the method to fetch data when component is mounted
},
methods: {
async fetchPosts() {
this.loading = true; // Set loading state to true when fetching starts
this.error = null; // Reset error state
try {
// 2. Use Axios to make a GET request
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
// 3. Handle successful response and store data
this.posts = response.data;
} catch (e) {
// 4. Handle errors
console.error('Error fetching posts:', e);
this.error = e.message || 'Something went wrong'; // Display error message
} finally {
this.loading = false; // Set loading state to false after request (success or error)
}
},
},
};
</script>
<style scoped>
/* Component-specific styles (optional) */
ul {
list-style-type: none;
padding: 0;
}
li {
margin-bottom: 20px;
padding: 15px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #f9f9f9;
}
h3 {
margin-top: 0;
color: #333;
}
p {
color: #555;
}
.error {
color: red;
}
.loading {
font-style: italic;
color: gray;
}
</style>
Practical Example: Working with Forms
This Vue component, SimpleFormExample
, showcases basic form handling by using v-model
for two-way data binding on text inputs and a textarea, linking them to the formData
data object. Upon form submission (preventing default page reload), the handleSubmit
method copies the form data to submittedData
for display, clears the input fields by resetting formData
, and shows a basic submission alert.
<template>
<div>
<h1>Simple Vue Form Example</h1>
<form @submit.prevent="handleSubmit">
<div>
<label for="name">Name:</label>
<input type="text" id="name" v-model="formData.name">
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" v-model="formData.email">
</div>
<div>
<label for="message">Message:</label>
<textarea id="message" v-model="formData.message"></textarea>
</div>
<button type="submit">Submit</button>
</form>
<div v-if="submittedData">
<h2>Submitted Data:</h2>
<p><strong>Name:</strong> {{ submittedData.name }}</p>
<p><strong>Email:</strong> {{ submittedData.email }}</p>
<p><strong>Message:</strong> {{ submittedData.message }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'SimpleFormExample',
data() {
return {
formData: {
name: '',
email: '',
message: ''
},
submittedData: null // To store the submitted data for display
};
},
methods: {
handleSubmit() {
// In a real application, you would likely send this data to a server.
// For this simple example, we'll just store it in 'submittedData' to display.
this.submittedData = { ...this.formData }; // Create a copy to avoid direct mutation
this.formData = { name: '', email: '', message: '' }; // Clear the form after submission
alert('Form submitted!'); // Basic feedback
}
}
};
</script>
Last updated
Was this helpful?