Skip to content
This repository was archived by the owner on May 1, 2025. It is now read-only.

Commit 4428d63

Browse files
authored
feat: content/1.vue/5.components (#63)
* chore: Rename a file in number order * feat: content/1.vue/5.components (#7)
1 parent 55861e8 commit 4428d63

File tree

8 files changed

+209
-2
lines changed

8 files changed

+209
-2
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script setup lang="ts">
2+
defineProps<{
3+
message: string
4+
name: string
5+
}>()
6+
7+
const emit = defineEmits<{
8+
'update:name': [string]
9+
}>()
10+
</script>
11+
12+
<template>
13+
<div class="child-component">
14+
<h2>Child Component</h2>
15+
<p>{{ message }}</p>
16+
<input
17+
type="text"
18+
:value="name"
19+
@input="emit('update:name', $event.target.value)"
20+
>
21+
</div>
22+
</template>
23+
24+
<style scoped>
25+
.child-component {
26+
border: solid red;
27+
padding: 1rem;
28+
}
29+
</style>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script setup lang="ts">
2+
import ChildComponent from './ChildComponent.vue'
3+
4+
const name = ref('John Doe')
5+
6+
function updateName(value: string) {
7+
name.value = value
8+
}
9+
</script>
10+
11+
<template>
12+
<div>
13+
<h1>Parent Component</h1>
14+
<p>Hi, {{ name }} 👋</p>
15+
<ChildComponent
16+
message="Hello from Parent!"
17+
:name="name"
18+
@update:name="updateName"
19+
/>
20+
</div>
21+
</template>

content/1.vue/5.components/.template/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export const meta: GuideMeta = {
44
startingFile: 'app.vue',
55
features: {
66
terminal: false,
7-
fileTree: false,
7+
fileTree: true,
88
navigation: false,
99
},
1010
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<script setup lang="ts">
2+
defineProps<{
3+
message: string
4+
}>()
5+
6+
const name = defineModel<string>()
7+
</script>
8+
9+
<template>
10+
<div class="child-component">
11+
<h2>Child Component</h2>
12+
<p>{{ message }}</p>
13+
<input
14+
v-model="name"
15+
type="text"
16+
>
17+
</div>
18+
</template>
19+
20+
<style scoped>
21+
.child-component {
22+
border: solid red;
23+
padding: 1rem;
24+
}
25+
</style>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script setup lang="ts">
2+
import ChildComponent from './ChildComponent.vue'
3+
4+
const name = ref('John Doe')
5+
</script>
6+
7+
<template>
8+
<div>
9+
<h1>Parent Component</h1>
10+
<p>Hi, {{ name }} 👋</p>
11+
<ChildComponent
12+
v-model="name"
13+
message="Hello from Parent!"
14+
/>
15+
</div>
16+
</template>

content/1.vue/5.components/index.md

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,117 @@
1-
# Components
1+
---
2+
ogImage: true
3+
---
4+
5+
# コンポーネント
6+
7+
Vue.js のコンポーネントは、UI を小さな再利用可能な部分に分割するための基本的な単位です。\
8+
特に Single File Components (SFC) を使うことで、HTML、CSS、および JavaScript を 1 つの `.vue` ファイルにまとめることができます。
9+
10+
## 基本的な SFC の構造
11+
12+
SFC は基本的に以下のような `<script>`, `<template>`, `<style>` の 3 つのセクションで構成されます。
13+
14+
```vue
15+
<script setup lang="ts">
16+
import { ref } from 'vue'
17+
18+
const message = ref('Hello, Vue!')
19+
20+
function sendMessage() {
21+
console.log(message.value)
22+
}
23+
</script>
24+
25+
<template>
26+
<p>{{ message }}</p>
27+
<button type="button" @click="sendMessage">
28+
Click me
29+
</button>
30+
</template>
31+
32+
<style scoped>
33+
p {
34+
color: red;
35+
}
36+
</style>
37+
```
38+
39+
この例では、`<script>`, `<template>`, `<style>` の 3 つのセクションが使われています。
40+
41+
- `<script setup>`: コンポーネントのロジック部分を定義します。`<script setup>` を使用することで、Composition API を簡潔に書くことができます。
42+
- `<template>`: コンポーネントのビュー部分を定義します。
43+
- `<style scoped>`: コンポーネント固有のスタイルを定義します。`scoped` 属性を追加することで、このコンポーネントのスタイルが他のコンポーネントに影響を与えないようにします。
44+
45+
## コンポーネントの再利用
46+
47+
`.vue` ファイルで定義した SFC は、以下のように `<script setup>` でインポートすることでテンプレート内で再利用することができます。
48+
49+
```vue
50+
<script setup lang="ts">
51+
import ChildComponent from './ChildComponent.vue'
52+
</script>
53+
54+
<template>
55+
<ChildComponent />
56+
</template>
57+
```
58+
59+
## コンポーネント間のデータの受け渡し
60+
61+
Vue コンポーネント間でデータをやり取りする基本的な方法として、`props``emit` を使用します。
62+
63+
- `props`: 親コンポーネントから子コンポーネントにデータを渡すための方法です。
64+
- `emit`: 子コンポーネントから親コンポーネントにイベントを発火するための方法です。
65+
66+
それぞれ `defineProps`, `defineEmits` で登録します。\
67+
使い方は右側のプレイグラウンド、または [API ドキュメント](https://ja.vuejs.org/api/sfc-script-setup.html#defineprops-defineemits)から確認できます。
68+
69+
## 双方向バインディング
70+
71+
コンポーネント上で `v-model` を使うことで双方向バインディングを実装できます。\
72+
以下の例では、コンポーネント中で宣言された `value``<input>` の値とバインドされ、`<input>` の入力値が `value` に反映されます。
73+
74+
```vue
75+
<script setup lang="ts">
76+
const value = ref('')
77+
</script>
78+
79+
<template>
80+
<input v-model="value" type="text">
81+
</template>
82+
```
83+
84+
また、SFC で `defineModel` を使うことで、親コンポーネントから `v-model` 経由で使用できる双方向バインディングの `props` を宣言できます。
85+
86+
```vue
87+
<!-- Child.vue -->
88+
<script setup lang="ts">
89+
const localValue = defineModel<string>()
90+
</script>
91+
92+
<template>
93+
<input v-model="localValue" type="text">
94+
</template>
95+
```
96+
97+
```vue
98+
<!-- Parent.vue -->
99+
<script setup lang="ts">
100+
import ChildComponent from './ChildComponent.vue'
101+
102+
const parentValue = ref('Initial Value')
103+
</script>
104+
105+
<template>
106+
<ChildComponent v-model="parentValue" />
107+
</template>
108+
```
109+
110+
## チャレンジ
111+
112+
プレイグラウンドの `ChildComponent.vue``props``emit` を使って双方向バインディングを実現しています。\
113+
これを `defineModel` を使って簡潔に書き直してみましょう。
114+
115+
もし手詰まりになったら、解決策を確認するためのボタンをクリックして、ヒントを得ることができます。
116+
117+
:ButtonShowSolution{.bg-faded.px4.py2.rounded.border.border-base.hover:bg-active.hover:text-primary.hover:border-primary:50}
File renamed without changes.

0 commit comments

Comments
 (0)