なぜ?
入力フォームを追加&削除できるようにv-for
でリストレンダリングさせて作っていたら、
1つの入力フィールドを変更すると、他の入力フィールドも連動して変更されてしまう・・・
v-model
でデータバインディングはそれぞれの要素を指しているのになんで???😭😭😭
ソースコード
以下のソースになります(サンプル)
<div id="app">
<div v-for="(item, index) in items"
:key="index"
>
<div>
<div>
<h3>No.{{ index + 1 }}.</h3>
<a v-if="totalCount > 1"
href="#"
@click.prevent="removeItems(index)"
>削除</a>
</div>
<div>
<p>タイトル</p>
<input type="text" v-model="item.title">
</div>
<div>
<p>内容</p>
<textarea v-model="item.content"></textarea>
</div>
</div>
</div>
<a v-if="!isLimitOver" href="#" @click.prevent="addItems">追加する</a>
</div>
const DEFAULT = {
title: 'タイトル',
content: '内容'
}
new Vue({
el: '#app',
data () {
return {
items: [DEFAULT],
count: 1,
limit: 10
}
},
computed: {
isLimitOver () {
return this.items.length >= this.limit
},
totalCount () {
return this.items.length
}
},
methods: {
addItems () {
this.items.push(DEFAULT)
this.count++
},
removeItems (target) {
this.items.splice(target, 1)
this.count--
}
}
})
原因
↓デフォルトの値を定義したこの定数オブジェクトが原因でした😂
const DEFAULT = {
title: 'タイトル',
content: '内容'
}
これは追加するたびに、定義された同じオブジェクトを配列にプッシュしていました。
したがって、新しい独立したオブジェクトではなく、同じオブジェクトの複数のコピーがある状態になっていたわけです💦
つまり、同じデータオブジェクトのため、全て共有されているので連動していたわけですね😓
解決策
データオブジェクトをコンポーネント内の関数にする✌️
new Vue({
el: '#app',
data () {
return {
items: [{
title: 'タイトル',
content: '内容'
}],
count: 1,
limit: 10
}
},
computed: {
isLimitOver () {
return this.items.length >= this.limit
},
totalCount () {
return this.items.length
}
},
methods: {
addItems () {
this.items.push(this.independentObejct())
this.count++
},
removeItems (target) {
this.items.splice(target, 1)
this.count--
},
/**
* 追加した関数
* @return {[Object]}
*/
independentObejct () {
return {
title: 'タイトル',
content: '内容'
}
}
}
})
コンポーネントのVueインスタンスが同じデータオブジェクトを共有しないように、
independentObejct()
メソッドとしてデータオブジェクトを関数にしました