0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vue3のリストレンダリングについて調べてみた

Posted at

Vue 3のComposition APIでリストレンダリングを行うには、主にv-forディレクティブを使い、リアクティブなデータソース(refreactiveで作成)をループ処理します。


基本的なリストレンダリング

基本的なリストレンダリングは、配列データをv-forで繰り返し描画します。

例:文字列の配列を表示する

<script setup>
import { ref } from 'vue';

// リアクティブな配列を定義
const fruits = ref(['🍎 りんご', '🍌 バナナ', '🍊 みかん']);
</script>

<template>
  <ul>
    <li v-for="fruit in fruits" :key="fruit">
      {{ fruit }}
    </li>
  </ul>
</template>

ポイント

  • ref: refを使って配列をリアクティブなデータにします。これにより、配列が変更されると自動的にUIが更新されます。
  • v-for: v-for="item in items"という形式で配列の各要素を繰り返します。
  • :key: key属性は、Vueが各ノードを識別し、効率的に描画を更新するために必須です。各要素で一意となる値を指定してください。要素に安定したIDがある場合はそれを使用するのがベストです。

オブジェクトの配列のレンダリング

実際のアプリケーションでは、オブジェクトの配列を扱うことがほとんどです。

例:ユーザー情報のリストを表示する

<script setup>
import { ref } from 'vue';

const users = ref([
  { id: 1, name: '山田 太郎', email: 'taro@example.com' },
  { id: 2, name: '鈴木 花子', email: 'hanako@example.com' },
  { id: 3, name: '佐藤 次郎', email: 'jiro@example.com' }
]);
</script>

<template>
  <div>
    <h2>ユーザーリスト</h2>
    <ul>
      <li v-for="user in users" :key="user.id">
        <p><strong>名前:</strong> {{ user.name }}</p>
        <p><strong>Email:</strong> {{ user.email }}</p>
      </li>
    </ul>
  </div>
</template>

ポイント

  • この例では、各ユーザーオブジェクトが持つ一意のid:keyにバインドしています。これは、リストの要素が追加、削除、または並べ替えられたときに、Vueが正確に変更を追跡するための最も確実な方法です。

インデックスの取得

v-forでは、要素と共にそのインデックスも取得できます。

<template>
  <ul>
    <li v-for="(item, index) in items" :key="item.id">
      {{ index }}: {{ item.name }}
    </li>
  </ul>
</template>

注意: 配列のインデックスを:keyとして使用することは、リストが以下のような特徴を持つ場合に限り推奨されます。

  1. リストが決して並べ替えられない。
  2. リストが決してフィルタリングされない。
  3. リストの要素が追加・削除される際、常に末尾でのみ行われる。

これらの条件を満たさない場合、インデックスをキーとして使うと、パフォーマンスの低下や状態の不整合を引き起こす可能性があります。
可能な限り、一意なIDをキーとして使用してください。


リストの操作

Composition APIでは、リアクティブな配列を直接変更するメソッドを定義して、リストを動的に操作できます。

例:アイテムの追加と削除

<script setup>
import { ref } from 'vue';

const items = ref([
  { id: 1, text: 'タスク1' },
  { id: 2, text: 'タスク2' }
]);
const newItemText = ref('');
let nextId = 3;

function addItem() {
  if (newItemText.value.trim() === '') return;
  items.value.push({
    id: nextId++,
    text: newItemText.value
  });
  newItemText.value = ''; // 入力欄をクリア
}

function removeItem(idToRemove) {
  items.value = items.value.filter(item => item.id !== idToRemove);
}
</script>

<template>
  <div>
    <input v-model="newItemText" @keyup.enter="addItem" placeholder="新しいタスクを入力">
    <button @click="addItem">追加</button>

    <ul>
      <li v-for="item in items" :key="item.id">
        <span>{{ item.text }}</span>
        <button @click="removeItem(item.id)">削除</button>
      </li>
    </ul>
  </div>
</template>

ポイント

  • 追加: items.value.push()のように、refで作成した配列の.valueプロパティに直接アクセスして配列操作メソッドを呼び出します。
  • 削除: filterメソッドを使って特定の要素を除外した新しい配列を生成し、items.valueに再代入しています。Vueはこの変更を検知してUIを更新します。
  • イベントハンドリング: @click@keyup.enterを使ってユーザーの操作とメソッドを紐付けます。

reactiveを使ったリストレンダリング

refの代わりにreactiveを使って、オブジェクトや配列をリアクティブにすることも可能です。reactiveはオブジェクトの深い階層までリアクティブにします。

<script setup>
import { reactive } from 'vue';

const state = reactive({
  users: [
    { id: 1, name: '田中' },
    { id: 2, name: '伊藤' }
  ]
});

function addUser() {
  state.users.push({ id: Date.now(), name: '新規ユーザー' });
}
</script>

<template>
  <button @click="addUser">ユーザー追加</button>
  <ul>
    <li v-for="user in state.users" :key="user.id">
      {{ user.name }}
    </li>
  </ul>
</template>

refreactiveの使い分け

  • ref: プリミティブ値(数値、文字列など)や、配列やオブジェクト全体を再代入する可能性がある場合によく使われます。
    .valueを介してアクセスする必要があります。
  • reactive: オブジェクトや配列に特化しており、.valueなしで直接プロパティにアクセスできます。
    トップレベルでの再代入はリアクティビティを失うため注意が必要です。

リストレンダリングにおいては、どちらを使っても機能しますが、コンポーネント内での状態管理のスタイルに合わせて選択すると良いでしょう。
一般的には、コンポーネントのトップレベルの状態として配列を管理する場合はrefがシンプルで分かりやすいことが多いです。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?