基礎からメモ: 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
このような目的では、グローバルAPIのVue.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自体も消える。