基礎からメモ: Vue.js CH2-p77 リスト要素の削除、更新

リストから特定の要素を削除

配列メソッドのspliceで、特定の要素をリストから削除する。

HTML側でリストの各要素に削除ボタンを追加。

[index12.html]

<ul>
    <li v-for="(item, index) in list" v-bind:key="item.id" >
      ID: {{ item.id }} {{ item.name }} HP: {{ item.hp }}
      <button v-on:click="doRemove(index)">モンスターを削除</button>
    </li>
</ul>

ボタンクリックでdoRemoveメソッドが起動し、その要素が削除される。

[main12.js]

.....
methods: {
    doRemove: function(index) {
      this.list.splice(index, 1);
    }
 }
.....

リスト操作に使える配列メソッド

  • push
  • pop
  • shift
  • unshift
  • splice
  • sort
  • reverse

注意: 算出プロパティを使ってリストを操作する場合は、配列インデックスは(変化する場合があるため)使わない。やはり要素のユニークなIDから操作する。

リストの置き換え

オブジェクトが個々の要素となった配列で、ある要素を一括更新する場合、配列のインデックス数値を使った代入はできない。

this.list[0] = { id: 1, name: 'キングスライム', hp: 500 }    // NG

このような目的では、グローバルAPIVue.set(エイリアスとしてはthis.$set)を使う。

this.$set(更新するデータ, インデックスorキー, 新しい値)

// sample
this.$set(this.list, 0, { id: 1, name: 'キングスライム', hp: 500 })

例えば次のようにリストの後ろに要素を変更するボタンと、変更する名前とHPの入力フォームを用意する。

<ul>
    <li v-for="(item, index) in list" v-bind:key="item.id" >
      ID: {{ item.id }} {{ item.name }} HP: {{ item.hp }}
      <button v-on:click="doChange(index)">モンスターを変更</button>
      名前:<input v-model="n_name">HP:<input v-model="n_hp">
    </li>
</ul>

Vueインスタンスに、変更する名前とHPを一時的に格納するデータプロパティを用意し、ボタンクリックで要素を変更するdoChangeメソッドを実装する。

var app = new Vue({
  el: '#app',
  data: {
      name: 'キマイラ',
      n_name: '新しい名前',
      n_hp: 100,
      list: [
          ........
      ]
  },
  methods: {
    doChange: function(index) {
      var ch_id = index + 1;
      this.$set(this.list, index, {id: ch_id, name: this.n_name, hp: this.n_hp});
    }
  }
})

プロパティの追加

もともと無かったプロパティを追加するのにも$setが使える。次のaddPropのようなメソッドを用意すれば、全ての要素に新たなプロパティを追加できる。

addProp: function(event) {
    this.list.forEach(function(item) {
       this.$set(item, this.n_prop, false)
    }, this);
}

引数のthis.n_propは、新たなプロパティを一時的に格納するためにdataに用意した任意の変数(n_prop: ””などとして初期値を渡しておくこと)。

リスト要素のプロパティを更新する

個々の要素まるごとではなく、個別のプロパティの値を変更する場合は、配列インデックスー>プロパティへのシンプルな方法が使える。

リストの要素がもつHPプロパティを変更してみる。

<!-- モンスターをのHPを10ずつ減らす  -->
<ul>
  <li v-for="(item, index) in list" v-bind:key="item.id" v-if="item.hp" >
    ID: {{ item.id }} {{ item.name }} HP: {{ item.hp }}
    <span v-if="item.hp < 50">瀕死! </span>
    <button v-on:click="doAttack(index)">攻撃する</button>
  </li>
</ul>
var app = new Vue({
  el: '#app',
  data: {
      list: [
        { id: 1, name: 'スライム', hp: 100 },
        { id: 2, name: 'ゴブリン', hp: 200 },
        { id: 3, name: 'ドラゴン', hp: 500 }
      ]
  },
  methods: {
    doAttack: function(index) {
        this.list[index].hp -= 10;
      }
    }
})

ボタンクリックでdoAttackメソッドが起動し、その要素のHPを10ずつ減らす。HPが50より小さくなると「瀕死!」の文字を表示する。liタグでv-if="item.hp"としているので、HPがゼロになったら消える。

リスト自体の置き換え

配列メソッドのfilterを使ってリストデータ自体を置き換える。

<ul>
    <li v-for="(item, index) in list" v-bind:key="item.id" >
      ID: {{ item.id }} {{ item.name }} HP: {{ item.hp }}
    </li>
</ul>
<button v-on:click="replaceList">HP:100より大きいものにする</button>

ボタンクリックでHPが100より大きいものだけがリストに残る。

......
methods: {
    replaceList: function() {
      this.list = this.list.filter(function(el) {
        return el.hp > 100;
      })
    }
 }
......

この場合は条件に合わなかった要素は、データ上もDOM自体も消える。

  • 特定の要素をリストから削除するには、methodsオプションで定義したメソッド内で配列メソッドのspliceを使う。
  • 要素を一括更新する場合、グローバルAPIVue.set(エイリアスthis.$set)を使う。
  • 要素の個別プロパティを変更する場合は、配列のインデックスからプロパティへのシンプルなアクセス方法が使える。