筆記 - Vue.js Intro (3) Components

透過 Vue.js 官網 tutorial 學習的筆記。學習標的為 Vue 3, using composition API.

Components - parent and child

Nested components are created in real Vue applications.

A parent component can render another component in its template as a child component.
import => use in the template

1
2
3
4
5
6
7
<script setup>
import ChildComp from './ChildComp.vue'
</script>

<template>
<ChildComp />
</template>

Props - parent to child

A child component can accept input from the parent via props.

First, it needs to declare the props it accepts:

1
2
3
4
5
6
7
8
9
10
<!-- ChildComp.vue -->
<script setup>
const props = defineProps({
msg: String
})
</script>

<template>
<h2>{{ msg || 'No props passed yet' }}</h2>
</template>

Note defineProps() is a compile-time macro and doesn’t need to be imported. Once declared, the msg prop can be used in the child component’s template. It can also be accessed in JavaScript via the returned object of defineProps().

The parent can pass the prop to the child just like attributes. To pass a dynamic value, we can also use the v-bind syntax:

1
2
3
4
5
6
7
8
9
10
<!-- App.vue -->
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'
const greeting = ref('Hello from parent')
</script>

<template>
<ChildComp :msg="greeting" />
</template>

Emits - child to parent

In addition to receiving props, a child component can also emit events to the parent:

1
2
3
4
5
6
7
8
9
10
11
<!-- ChildComp.vue -->
<script setup>
// declare emitted events
const emit = defineEmits(['response'])
// emit with argument
emit('response', 'hello from child')
</script>

<template>
<h2>Child component</h2>
</template>

The first argument to emit() is the event name. Any additional arguments are passed on to the event listener.

The parent can listen to child-emitted events using v-on - here the handler receives the extra argument from the child emit call and assigns it to local state:

1
2
3
4
5
6
7
8
9
10
11
<!-- App.vue -->
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'
const childMsg = ref('No child msg yet')
</script>

<template>
<ChildComp @response="(msg) => childMsg = msg" />
<p>{{ childMsg }}</p>
</template>

Slots: template fragments from parent to child

In addition to passing data via props, the parent component can also pass down template fragments to the child via slots:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- App.vue -->
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'
const msg = ref('from parent')
</script>

<template>
<ChildComp>Message: {{ msg }}</ChildComp>
</template>

<!-- ChildComp.vue -->
<template>
<slot>Fallback content</slot>
</template>

In child component, the content inside the outlet will be treated as “fallback” content: it will be displayed if the parent did not pass down any slot content.