@@ -9,7 +9,7 @@ Vue.js のコンポーネントは、UI を小さな再利用可能な部分に
9
9
10
10
## 基本的な SFC の構造
11
11
12
- SFC は基本的に以下のような ` <script> ` , ` <template> ` , ` <style> ` の 3 つのセクションで構成されます。
12
+ SFC は基本的に以下のような ` <script setup > ` , ` <template> ` , ` <style> ` の 3 つのセクションで構成されます。
13
13
14
14
``` vue
15
15
<script setup lang="ts">
36
36
</style>
37
37
```
38
38
39
- この例では、` <script> ` , ` <template> ` , ` <style> ` の 3 つのセクションが使われています。
39
+ この例では、` <script setup > ` , ` <template> ` , ` <style> ` の 3 つのセクションが使われています。
40
40
41
41
- ` <script setup> ` : コンポーネントのロジック部分を定義します。` <script setup> ` を使用することで、Composition API を簡潔に書くことができます。
42
42
- ` <template> ` : コンポーネントのビュー部分を定義します。
48
48
49
49
``` vue
50
50
<script setup lang="ts">
51
- import ChildComponent from './ChildComponent .vue'
51
+ import Child from './Child .vue'
52
52
</script>
53
53
54
54
<template>
55
- <ChildComponent />
55
+ <Child />
56
56
</template>
57
57
```
58
58
59
59
## コンポーネント間のデータの受け渡し
60
60
61
61
Vue コンポーネント間でデータをやり取りする基本的な方法として、` props ` と ` emit ` を使用します。
62
62
63
- - ` props ` : 親コンポーネントから子コンポーネントにデータを渡すための方法です。
64
- - ` emit ` : 子コンポーネントから親コンポーネントにイベントを発火するための方法です。
63
+ ### Props
65
64
66
- それぞれ ` defineProps ` , ` defineEmits ` で登録します。\
67
- 使い方は右側のプレイグラウンド、または [ API ドキュメント] ( https://ja.vuejs.org/api/sfc-script-setup.html#defineprops-defineemits ) から確認できます。
65
+ 親コンポーネントから子コンポーネントにデータを渡すための方法です。
68
66
69
- ## 双方向バインディング
70
-
71
- コンポーネント上で ` v-model ` を使うことで双方向バインディングを実装できます。\
72
- 以下の例では、コンポーネント中で宣言された ` value ` が ` <input> ` の値とバインドされ、` <input> ` の入力値が ` value ` に反映されます。
67
+ まずは子コンポーネント側で ` defineProps ` マクロを使用し、受け取りたいデータを定義します。
73
68
74
69
``` vue
70
+ <!-- Child.vue -->
75
71
<script setup lang="ts">
76
- const value = ref('' )
72
+ defineProps<{ message: string }>( )
77
73
</script>
74
+ ```
78
75
76
+ 次に親コンポーネント側で、子コンポーネントにデータを渡すために ` v-bind ` ディレクティブを使用します。\
77
+ ` :props名="データ" ` という形式で、子コンポーネントにデータを渡すことができます。
78
+
79
+ ``` vue
80
+ <!-- Parent.vue -->
79
81
<template>
80
- <input v-model="value" type="text" >
82
+ <Child :message="message" / >
81
83
</template>
82
84
```
83
85
84
- また、SFC で ` defineModel ` を使うことで、親コンポーネントから ` v-model ` 経由で使用できる双方向バインディングの ` props ` を宣言できます。
86
+ また、props 名とデータの変数名が同名の場合は省略記法を使うことができます。
87
+
88
+ ``` vue
89
+ <!-- Parent.vue -->
90
+ <template>
91
+ <Child :message />
92
+ </template>
93
+ ```
94
+
95
+ ### Emit
96
+
97
+ 子コンポーネントから親コンポーネントにイベントを発火するための方法です。
98
+
99
+ まずは子コンポーネント側で ` defineEmits ` マクロを使用し、発火したいイベントを定義します。
100
+ emit 関数を用いて、イベントを発火することができます。
85
101
86
102
``` vue
87
103
<!-- Child.vue -->
88
104
<script setup lang="ts">
89
- const localValue = defineModel<string >()
105
+ const emit = defineEmits<{ sendMessage: [] } >()
90
106
</script>
91
107
92
108
<template>
93
- <input v-model="localValue" type="text">
109
+ <button type="button" @click="emit('sendMessage')">
110
+ Click me
111
+ </button>
94
112
</template>
95
113
```
96
114
115
+ 発火されたイベントは親コンポーネント側で ` v-on ` ディレクティブを使用して受け取ることができます。
116
+
97
117
``` vue
98
118
<!-- Parent.vue -->
99
119
<script setup lang="ts">
100
- import ChildComponent from './ChildComponent.vue'
120
+ function handleSendMessage() {
121
+ console.log('Message sent!')
122
+ }
123
+ </script>
101
124
102
- const parentValue = ref('Initial Value')
125
+ <template>
126
+ <Child @send-message="handleSendMessage" />
127
+ </template>
128
+ ```
129
+
130
+ 以下のように、イベント発火時に子コンポーネントからデータを受け渡すこともできます。
131
+
132
+ ``` vue
133
+ <!-- Child.vue -->
134
+ <script setup lang="ts">
135
+ const emit = defineEmits<{ sendMessage: [string] }>()
103
136
</script>
104
137
105
138
<template>
106
- <ChildComponent v-model="parentValue" />
139
+ <button type="button" @click="emit('sendMessage', 'Hello, Vue!')">
140
+ Click me
141
+ </button>
107
142
</template>
108
143
```
109
144
110
- ## チャレンジ
145
+ ``` vue
146
+ <!-- Parent.vue -->
147
+ <script setup lang="ts">
148
+ function handleSendMessage(message: string) {
149
+ console.log(message)
150
+ }
151
+ </script>
111
152
112
- プレイグラウンドの ` ChildComponent.vue ` は ` props ` と ` emit ` を使って双方向バインディングを実現しています。\
113
- これを ` defineModel ` を使って簡潔に書き直してみましょう。
153
+ <template>
154
+ <Child @send-message="handleSendMessage" />
155
+ </template>
156
+ ```
114
157
115
- もし手詰まりになったら、解決策を確認するためのボタンをクリックして、ヒントを得ることができます。
158
+ それぞれの詳しい [ API ドキュメント] ( https://ja.vuejs.org/api/sfc-script-setup.html#defineprops-defineemits ) から確認することができます。
159
+
160
+ ## チャレンジ
116
161
117
- : ButtonShowSolution { . bg-faded . px4 . py2 . rounded . border . border-base . hover:bg-active . hover:text-primary . hover:border-primary:50 }
162
+ 右のプレイグラウンドでは、props と emit を使ってコンポーネント間のデータの受け渡しを行っています。\
163
+ Vue.js では [ スロット] ( https://ja.vuejs.org/guide/components/slots.html ) という機能を利用することで、親コンポーネントからコンポーネントにテンプレートを挿入することができます。\
164
+ 右のプレイグラウンドを編集して、スロットを使ったテンプレートの挿入を行ってみましょう。
165
+
166
+ 1 . 子コンポーネント (` Child.vue ` ) でスロットの定義を行う\
167
+ [ defineSlot マクロ] ( https://ja.vuejs.org/api/sfc-script-setup.html#defineslots ) を使うことにより、型安全なスロットを定義することができます。\
168
+ 定義ができたら、template 内で ` slot ` タグを配置することで渡されたテンプレートの挿入を行うことができます。
169
+
170
+ ``` vue
171
+ <script setup lang="ts">
172
+ defineSlots<{ paragraph: () => any }>()
173
+ </script>
174
+
175
+ <template>
176
+ <h2>Child Component</h2>
177
+ <p><slot name="paragraph" /></p>
178
+ </template>
179
+ ```
180
+
181
+ 2 . 親コンポーネント (` app.vue ` ) で slot にテンプレートを挿入する\
182
+ 親コンポーネント側で、子コンポーネントにテンプレートを挿入するために ` v-slot ` ディレクティブを使用します。\
183
+ (ここでは ` v-slot ` の省略記法の ` # ` を使用しています)
184
+
185
+ ``` vue
186
+ <template>
187
+ <Child>
188
+ <template #paragraph>
189
+ Hello from <span class="red--text">Parent!</span>
190
+ </template>
191
+ </Child>
192
+ </template>
193
+ ```
194
+
195
+ : ButtonShowSolution { . bg-faded . px4 . py2 . rounded . border . border-base . hover:bg-active . hover:text-primary . hover:border-primary:50 }
0 commit comments