Module: Vue Components Basics

Creating components

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:

  1. Globally Registered Components: Available in any Vue instance within your application.
  2. 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 named my-component.
  • The object passed as the second argument defines the component's options.
  • template specifies 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 MyLocalComponent from a separate file.
  • The components option is an object where the keys are the component names and the values are the component definitions.
  • MyLocalComponent is 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 message and number props to MyComponent.
  • The child component defines the props option to declare the props it expects.
  • type specifies the expected data type.
  • required indicates whether the prop is mandatory.
  • default provides a default value if the prop is not provided. The : before number is shorthand for v-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.