javascript - Vue removing wrong HTML node in dynamic list of components -
i'm experimenting vue.js , composing components dynamically.
there's strange issue although seems updating data correctly, if remove 1 of boxes call splice()
removes last item in rendered html.
here's example fiddle. i'm testing in chrome.
https://jsfiddle.net/afz6jjn0/
just posterity, here's vue component code:
vue.component('content-longtext', { template: '#content-longtext', props: { model: { type: string, required: true }, update: { type: function, required: true } }, data() { return { inputdata: this.model } }, methods: { updatecontent(event) { this.update(event.target.value) } }, }) vue.component('content-image', { template: '#content-image', }) vue.component('content-list', { template: '#content-list-template', props: { remove: { type: function, required: true }, update: { type: function, required: true }, views: { type: array, required: true } }, methods: { removecontent(index) { this.remove(index) }, updatecontent(index) { return (content) => this.update(index, content) }, }, }) vue.component('content-editor', { template: '#content-editor', data() { return { views: [ {type: 'content-longtext', model: 'test1'}, {type: 'content-longtext', model: 'test2'}, {type: 'content-longtext', model: 'test3'}, {type: 'content-longtext', model: 'test4'}, {type: 'content-longtext', model: 'test5'}, ], } }, methods: { newcontentblock(type) { this.views.push({type: 'content-longtext', model: ''}) }, updatecontentblock(index, model) { this.views[index].model = model }, removecontentblock(index) { this.views.splice(index, 1) }, }, }) let app = new vue({ el: '#app' })
i've managed fix issue this documentation.
the crux of if don't have unique key already, need store array index of object in object itself, because mutate source array mutating it's keys , far vue concerned when renders, last item missing, not removed item.
views: [ {index: 0, type: 'content-longtext', model: 'test1'}, {index: 1, type: 'content-longtext', model: 'test2'}, {index: 2, type: 'content-longtext', model: 'test3'}, {index: 3, type: 'content-longtext', model: 'test4'}, {index: 4, type: 'content-longtext', model: 'test5'}, ], ... newcontentblock(type) { this.views.push({index: this.views.length, type: 'content-longtext', model: ''}) },
once have stored array index need add :key
binding iterator in template, , bind stored value.
<div v-for="(currentview, index) in views" :key="currentview.index"> <component :is="currentview.type" :model="currentview.model" :update="updatecontent(index)"></component> <a v-on:click="removecontent(index)">remove</a> </div>
finally must make sure preserve integrity of indexes when mutate array.
removecontentblock(index) { this.views .splice(index, 1) .map((view, index) => view.index = index) },
Comments
Post a Comment