An Introduction to Vue Components

Components are essentially custom HTML elements. They allow you to break your app down into understandable and reusable chunks, rather than having a single monolithic app. In this tutorial, you'll learn:

How to create a component

How to manage internal state with a component

How to pass data into a component via props

How to pass data from a component to its parent via $emit()

Creating a Component

To create a component, you should call the Vue.component() function. The Vue.component() function takes 2 parameters: a unique string id for the component, and the object definition of the component.

Suppose you have a component whose id is hello . Whenever you include an element <hello></hello> in a Vue template, Vue will replace the element with your component's template. Below is an example of a component hello with a template that displays a message in an <h1> tag.

const helloComponent = Vue.component( 'hello' , { template : '<h1>Hello, World</h1>' }); typeof helloComponent; helloComponent.name; Vue.options.components[ 'hello' ] === helloComponent; const app = new Vue({ template : '<hello></hello>' }); app.$mount( '#content' );

Internal State With Components

One advantage Vue has over React is two way data binding on form elements. Forms in Vue are trivial using v-model , but they require a bit more work with React.

Suppose you wanted to extend the hello component with an input, so the user can enter their name. You should add a data function to your component definition that returns the initial state of the component. Make sure you define an initial state for all the properties you want Vue to watch, even if it is null .

Vue.component( 'hello' , { data : () => ({ name : 'World' }), template : ` <div> <div> <input v-model="name"></input> </div> <h1>Hello, {{name}}</h1> </div> ` }); const app = new Vue({ template : '<hello></hello>' }); app.$mount( '#content' );

Here's how the component looks in action. You can also see a live example here.

Component Props

Suppose that, instead of having one component that handles both user input and displaying data, you want to have separate components. The top-level app template will display the <input> , and the hello component will be responsible for displaying the value of the <input> .

The way to pass data to the hello component is using props. The v-bind:name="name" binds the value of name in the hello component's template to the value of name in the top-level app state.

Vue.component( 'hello' , { props : [ 'name' ], template : '<h1>Hello, {{name}}</h1>' }); const app = new Vue({ data : () => ({ name : 'World' }), template : ` <div> <div> <input v-model="name"></input> </div> <hello v-bind:name="name"></hello> </div> ` });

Here's a live example of the props-based hello component.

$emit()

Props let you pass data into a component from a parent component. The $emit() function lets you pass data from a component back to its parent, usually in response to an event.

Suppose you wanted to define a separate input-name component that allowed the user to input their name. When the user clicks the 'Update' button, your app updates the user's name and updates the <h1> tag. Here's how this works in Vue:

Vue.component( 'input-name' , { data : () => ({ name : 'World' }), template: ` <div> <input type="text" v-model="name"> <button v-on:click="$emit('update', name)"> Update </button> </div> ` }); const app = new Vue({ data : () => ({ name : 'World' }), template: ` <div> <div> <input-name v-on:update="setName($event)"></input-name> </div> <h1>Hello, {{name}}</h1> </div> ` , methods : { setName: function ( v ) { this .name = v; } } }); app.$mount( '#content' );

Here's a live example.

More Vue Tutorials