5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vueコンポーネントのことはじめ色々

Posted at

コンポーネント化

Vueではパーツごとにコンポーネントを細かく分ける。

Item.vue
<script setup lang="ts">
import { ref } from 'vue'
import ItemPostForm from './ItemPostForm.vue';
import ItemList from './ItemList.vue';
const items = ref([{ id: 0, name: "ポーション", price: 100 }, { id: 2, name: "ハイポーション", price: 200 }])

const postItem = (name: string, price: number) => {
  const item = { id: Math.random(), name, price };
  items.value.push(item);
  inputtingName.value = "";
  inputtingPrice.value = 0;
}

const deleteItem = (id: number) => {
  items.value = items.value.filter(t => t.id != id)
}
</script>

<template>
  <div class="container">
    <h1>アイテム屋</h1>
    <ItemPostForm @post-item="postItem"/>
    <div class="item-container">
      <p v-if="items.length <= 0">Sold Out</p>
      <ul v-else>
        <ItemList :items="items" @delete-item="deleteItem"/>
      </ul>
    </div>
  </div>
</template>
ItemList.vue
<script setup lang="ts">
import { defineProps } from 'vue';
type Item = {
    id: number,
    name: string,
    price: number,
}

type Props = {
    items: Item[]
}

// Propsとして受け取る
// 基本的に子コンポーネントでは値を変更しない
defineProps<Props>()

const emit = defineEmits(['delete-item'])
const deleteItem = (id: number) => {
    emit('delete-item', id)
}
</script>

<template>
        <li v-for="item in items" :key="item.id" class="item-list">
          <span>{{ item.name }} {{ item.price }}</span>
          <button class="delete-button" @click="deleteItem(item.id)">delete</button>
    </li>
</template>
ItemPostForm.vue
<script setup lang="ts">
import { ref, defineEmits } from 'vue'
const inputtingName = ref<string>("");
const inputtingPrice = ref<number>(0);

// 子から親へのイベント伝播
const emit = defineEmits(['post-item'])
const postItem = () => {
  emit('post-item', inputtingName.value, inputtingPrice.value)
}
</script>

<template>
    <div class="form-container">
      <input v-model="inputtingName"/>
      <input v-model="inputtingPrice"/>
      <button class="save-button" @click="postItem()">post</button>
    </div>
</template>

親コンポーネントから子コンポーネントへの伝播 Props

Item.vue
<script setup lang="ts">
import { ref } from 'vue'
import ItemList from './ItemList.vue';const items = ref([{ id: 0, name: "ポーション", price: 100 }, { id: 2, name: "ハイポーション", price: 200 }])
</script>

<template>
  <div class="container">
    <h1>アイテム屋</h1>
    <ItemPostForm"/>
    <div class="item-container">
      <p v-if="items.length <= 0">Sold Out</p>
      <ul v-else>        
        <!-- v-bindで値を渡す。v-bindは省略できる。
        v-bind:itemsと同じ -->
        <ItemList :items="items"/>
      </ul>
    </div>
  </div>
</template>
ItemList.vue
<script setup lang="ts">
import { defineProps } from 'vue';
type Item = {
    id: number,
    name: string,
    price: number,
}

// Propsを定義
type Props = {
    items: Item[]
}

// Propsとして受け取る
// 基本的に子コンポーネントでは値を変更しない
defineProps<Props>()
</script>

子コンポーネントから親コンポーネントへの伝播 Emit

VueではEmitで伝播させる。
v-bindも利用可能だが非推奨。

Item.vue
<script setup lang="ts">
import { ref } from 'vue'
import ItemPostForm from './ItemPostForm.vue';
import ItemList from './ItemList.vue';
const items = ref([{ id: 0, name: "ポーション", price: 100 }, { id: 2, name: "ハイポーション", price: 200 }])

// javascriptではkeyと引数の値が同じであれば両略できる
// name:name, price:priceに同じ
const postItem = (name: string, price: number) => {
  const item = { id: Math.random(), name, price };
  items.value.push(item);
  inputtingName.value = "";
  inputtingPrice.value = 0;
}

const deleteItem = (id: number) => {
  items.value = items.value.filter(t => t.id !== id)
}
</script>

<template>
  <div class="container">
    <h1>アイテム屋</h1>
    <!-- postItem関数に伝播させる -->
    <ItemPostForm @post-item="postItem"/>
    <div class="item-container">
      <p v-if="items.length <= 0">Sold Out</p>
      <ul v-else>
        <!-- deleteItem関数に伝播させる -->
        <ItemList :items="items" @delete-item="deleteItem"/>
      </ul>
    </div>
  </div>
</template>
ItemPostForm.vue
<script setup lang="ts">
import { ref, defineEmits } from 'vue'
const inputtingName = ref<string>("");
const inputtingPrice = ref<number>(0);

// emitでイベント伝播
// 大文字は小文字に変換し、ハイフンを付ける
// postItem -> post-item
const emit = defineEmits(['post-item'])
const postItem = () => {
  emit('post-item', inputtingName.value, inputtingPrice.value)
}
</script>
ItemList.vue
<script setup lang="ts">
import { defineProps } from 'vue';
type Item = {
    id: number,
    name: string,
    price: number,
}

type Props = {
    items: Item[]
}
defineProps<Props>()

// emitでイベント伝播
// 大文字は小文字に変換し、ハイフンを付ける
// deleteItem -> delete-item
const emit = defineEmits(['delete-item'])
const deleteItem = (id: number) => {
    emit('delete-item', id)
}
</script>

参考

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?