Passing Data Between Vue Components
JavaScript, Vue
Components are re-usable Vue instances that better allow you to keep code separated and modular. They are very flexible - child components can be defined and used within parents. This can be a really useful way of preventing repetitive markup.
Single-file components take things to the next level. These keep all component data within a single .vue
file - comprised of a HTML like structure with <template>
(markup), <script>
(JavaScript) and <style>
(CSS) components. This can be really useful for larger projects or projects in which the entire frontend is built in JavaScript.
If you use vue-cli
to spin up a Vue/Webpack project, the project comes with single-file components pre-installed.
This article outlines how to pass data between components in the context of single file components.
Passing Data From Parent Component to Child Component
Import Child in Parent Component
Import the child component so that it can be used in the parent, and declare the component in the <script>
section:
<script>
// @ is an alias to /src (in a vue-cli generated project)
import Child from '@/components/Child.vue'
// You also need to declare that the imported child component will be used:
export default {
components: {
Child
}
}
</script>
Invoke the Child Component in the Parent
Within the <template>
section of the parent component, call the child component. Prop data is passed as an attribute.
You can pass data inline, or define it within the data()
method of the component.
<template>
<div>
<!-- simplest prop - pass a string -->
<Child title="This is my title"></Child>
<!-- Pass an object, defined inline -->
<Child :parentData="{msg: 'xxx'}"></Child>
<!-- Pass an object, defined in the `data()` method -->
<Child :parentData="myData"></Child>
<!-- Pass a string variable, defined in `data()`. Note colon. -->
<Child :stringProp="stringMessage"></Child>
</div>
</template>
Note that prepending a colon to the prop attribute indicates that a variable is passed, not a string.
Receiving the Prop Data in the Child
You must declare the prop in the child component <script>
section - you can then use it as a normal Vue-defined variable:
<script>
export default {
name: 'Child',
// To use props, they must be declared
props: {
parentData: Object,
stringProp: String,
title: String
}
}
</script>
Pass Data from Child to Parent
You can send data from a child to a parent component by means of Vue’s built-in $emit()
method. The first parameter of $emit
is the event that should be listened for in the parent component. The second (optional) parameter is the data value to pass.
Parent:
<!-- Parent.vue -->
<template>
<div>
<!--
Listen for `childToParent`: the first parameter of the `$emit` method
in the child component. We're also listening and reacting to an
`increment` event - in this case, we increment a counter inline.
-->
<Child :parentData="myData" v-on:childToParent="onChildClick" v-on:increment="counter++"></PassProps>
</div>
</template>
<script>
import Child from '@/components/Child.vue'
export default {
data () {
return {
counter: 0,
fromChild: '', // This value is set to the value emitted by the child
}
},
name: 'about',
components: {
Child
},
methods: {
// Triggered when `childToParent` event is emitted by the child.
onChildClick (value) {
this.fromChild = value
}
}
}
</script>
In this example, the parent listens for the childToParent
event (defined by the $emit
method) and triggers the onChildClick()
method when the event is received. This method in turn sets the fromChild
variable. It also emits an increment
event in a simpler way when the button is clicked, by placing $emit
inline in the template.
In the child component:
<!-- Child.vue -->
<template>
<div class="child">
<!-- Simplest - call `$emit()` inline-->
<button type="button" name="button" v-on:click="$emit('increment')">Click me to increment!</button>
<!-- set a variable then trigger a method which calls `$emit()` -->
<label for="child-input">Child input: </label>
<input id="child-input" type="text" name="msg" v-model="childMessage" v-on:keyup="emitToParent">
</div>
</template>
<script>
export default {
data() {
return {
childMessage: ''
}
},
name: 'Child',
methods: {
// Define the method that emits data to the parent as the first parameter to `$emit()`.
// This is referenced in the <template> call in the parent. The second parameter is the payload.
emitToParent (event) {
this.$emit('childToParent', this.childMessage)
}
}
}
</script>
This example emits a user-entered string back to the parent component.
comments powered by Disqus