Vue Components Basics: Creating Components
Vue.js is built around the concept of components. Components are reusable, self-contained units of UI that encapsulate HTML, CSS, and JavaScript. They allow you to break down complex UIs into smaller, manageable pieces, making your code more organized, maintainable, and reusable.
What are Components?
Think of components like custom HTML elements. You define them once, and then you can use them multiple times throughout your application. Each component has its own:
- Template: The HTML structure of the component.
- Script: The JavaScript logic that powers the component (data, methods, computed properties, etc.).
- Style: The CSS that styles the component.
Defining a Component
There are two main ways to define a component in Vue:
- Globally Registered Components: Available in any Vue instance within your application.
- Locally Registered Components: Only available within the Vue instance where they are registered.
Let's start with a simple example of a globally registered component:
// main.js (or your entry point)
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Define a global component
app.component('my-component', {
template: '<div>This is a global component!</div>'
})
app.mount('#app')
In this example:
app.component('my-component', { ... })registers a component namedmy-component.- The object passed as the second argument defines the component's options.
templatespecifies the HTML that will be rendered when the component is used.
Now you can use <my-component> in any template within your application.
Using the global component in a template (e.g., App.vue):
<template>
<div>
<h1>My App</h1>
<my-component></my-component>
</div>
</template>
Locally Registered Components
Locally registered components are generally preferred because they provide better encapsulation and avoid potential naming conflicts.
<template>
<div>
<h1>My App</h1>
<my-local-component></my-local-component>
</div>
</template>
<script>
import MyLocalComponent from './components/MyLocalComponent.vue'
export default {
components: {
MyLocalComponent // Register the component locally
}
}
</script>
In this example:
- We import the component
MyLocalComponentfrom a separate file. - The
componentsoption is an object where the keys are the component names and the values are the component definitions. MyLocalComponentis only available within this Vue instance.
MyLocalComponent.vue (example):
<template>
<div>This is a local component!</div>
</template>
<script>
export default {
name: 'MyLocalComponent' // Optional, but good practice
}
</script>
Component Options
Here's a breakdown of common component options:
template: (String) The HTML template for the component.data: (Function) A function that returns an object containing the component's reactive data. Must be a function to ensure each instance has its own data.methods: (Object) An object containing methods that can be called from the template or other methods.computed: (Object) An object containing computed properties, which are derived from the component's data and are cached.props: (Array or Object) Defines the data that can be passed to the component from its parent.watch: (Object) Allows you to react to changes in data.components: (Object) Registers locally available components.name: (String) Optional, but useful for debugging and recursive components.mounted: (Function) Lifecycle hook called after the component is mounted to the DOM.created: (Function) Lifecycle hook called after the component instance is created.
Passing Data to Components with Props
Props are how you pass data from a parent component to a child component.
Parent Component (e.g., App.vue):
<template>
<div>
<my-component message="Hello from parent!" :number="123"></my-component>
</div>
</template>
<script>
import MyComponent from './components/MyComponent.vue'
export default {
components: {
MyComponent
}
}
</script>
Child Component (MyComponent.vue):
<template>
<div>
<p>Message: {{ message }}</p>
<p>Number: {{ number }}</p>
</div>
</template>
<script>
export default {
props: {
message: {
type: String,
required: true,
default: ''
},
number: {
type: Number,
default: 0
}
}
}
</script>
In this example:
- The parent component passes the
messageandnumberprops toMyComponent. - The child component defines the
propsoption to declare the props it expects. typespecifies the expected data type.requiredindicates whether the prop is mandatory.defaultprovides a default value if the prop is not provided. The:beforenumberis shorthand forv-bind:number, which dynamically binds the value.
Component Communication (Beyond Props)
While props are the primary way to pass data down the component tree, other mechanisms exist for communication:
- Events: Child components can emit events that parent components can listen for. (Using
$emit) - Provide/Inject: Allows a parent component to provide data to all its descendants, regardless of how deeply nested they are.
- Vuex (or Pinia): A state management library for more complex applications, providing a centralized store for data.
This provides a foundational understanding of Vue components. As you build more complex applications, you'll explore more advanced concepts like slots, mixins, and functional components.