#1 How To Communicate Between Parent And Child Components
Saturday, August 8, 2020
In this video we discuss how to handle component communication between a parent and one or more children. We will start off by simply passing data from the parent to the child and move on to handling events emitted from the child which the parent can then listen for and respond to. Both of these interactions can be handled very easily by just using the normal tools provided by Vue itself. We will then finish up by discussing a couple of different ways of handling events that take place within the scope of the parent component as using those to trigger actions within the children.
Parts
- Part 1: Component Communication
Code Snippets
Child.vue
<template lang="pug">
div.p-5.bg-blue-100
...
div {{parentMessage}}
</template>
Child.vue
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
@Component
export default class Child extends Vue {
@Prop({ default: "[undefined]" }) private readonly parentMessage!: string;
}
</script>
Parent.vue
<template lang="pug">
div.p-5.bg-green-100
...
input.p-2.w-full.mb-2(v-model="parentMessage")
div.mb-2 {{parentMessage}}
Child(v-bind:parentMessage="parentMessage")/
</template>
Parent.vue
<script lang="ts">
...
export default class Parent extends Vue {
private parentMessage = "Parent starting message!";
}
</script>
Child.vue
<template lang="pug">
div.p-5.bg-blue-100
...
div.flex.mb-2
input.p-2.flex-1(v-model="childMessage")
button.button(v-on:click.prevent="save") Save
...
</template>
Child.vue
<script lang="ts">
...
export default class Child extends Vue {
...
private childMessage = "The child message";
private save() {
this.$emit("save", this.childMessage);
}
}
</script>
Parent.vue
<template lang="pug">
div.p-5.bg-green-100
...
Child(
v-bind:parentMessage="parentMessage"
v-on:save="save")/
</template>
Parent.vue
<script lang="ts">
...
export default class Parent extends Vue {
...
private save(childMessage: string) {
this.parentMessage = childMessage;
}
...
}
</script>
Child.vue
<script lang="ts">
import { ..., Watch } from "vue-property-decorator";
export enum Commands {
None,
Clear,
}
...
export default class Child extends Vue {
@Prop({ default: Commands.None }) private readonly command!: Commands;
...
@Watch("command")
private watchCommand() {
switch (this.command) {
case Commands.None:
console.log("Nothing to do.")
break;
case Commands.Clear:
this.childMessage = "";
break;
}
}
}
</script>
Advertisement
Parent.vue
<template lang="pug">
div.p-5.bg-green-100
...
button.button.mb-2(v-on:click.prevent="clearChildren") Clear
Child(
v-bind:command="childCommand"
v-bind:parentMessage="parentMessage"
v-on:save="save")/
</template>
Parent.vue
<script lang="ts">
...
import ..., { Commands } from "@/components/component-communication/Child.vue";
...
export default class Parent extends Vue {
private childCommand = Commands.None;
...
private clearChildren() {
this.childCommand = Commands.Clear;
this.childCommand = Commands.None;
}
...
}
</script>
Parent.vue
<script lang="ts">
...
export default class Parent extends Vue {
...
private clearChildren() {
this.childCommand = Commands.Clear;
requestAnimationFrame(() => {
this.childCommand = Commands.None;
});
}
...
}
</script>
observable.ts
type Subscription<T> = (x: T) => void;
export class Observable<T> {
private callbacks: Array<Subscription<T>> = [];
public next(input: T) {
this.callbacks.forEach((x) => x(input));
}
public subscribe(subscription: Subscription<T>) {
this.callbacks.push(subscription);
}
}
Child.vue
<script lang="ts">
...
import { Observable } from "@/components/component-communication/observable";
...
export default class Child extends Vue {
@Prop() private readonly observable!: Observable<Commands>;
...
private mounted() {
this.observable.subscribe(this.runCommand);
}
private runCommand(command: Commands) {
switch (command) {
case Commands.None:
console.log("Nothing to do.");
break;
case Commands.Clear:
this.childMessage = "";
break;
}
}
...
}
</script>
Parent.vue
<template lang="pug">
div.p-5.bg-green-100
...
Child(
v-bind:observable="observable"
v-bind:parentMessage="parentMessage"
v-on:save="save")/
</template>
Parent.vue
<script lang="ts">
...
import { Observable } from "@/components/component-communication/observable";
...
export default class Parent extends Vue {
private observable = new Observable<Commands>();
...
private clearChildren() {
this.observable.next(Commands.Clear);
}
...
}
</script>
Exciton Interactive LLC