我正在创建一个VueJs父组件,该组件可以动态创建行,并且该组件调用另一个可以使用axios填充2个下拉列表的组件。 一类 第二个用于子类别(此下拉列表可能取决于第一个)
这是添加行的第一个组件
<template>
<div>
<ul>
<li v-for="(input, index) in inputs" :key="index">
<request-part :index="index" :input="input" :inputs="inputs">
</request-part>
<hr />
</li>
</ul>
<button
type="button"
@click="addRow"
class="btn font-montserrat-regular btn-success btn-plus bt-radius-add"
>
Onderdeel toevoegen
</button>
</div>
</template>
<script>
export default {
data() {
return {
category: null,
selectedFile: null,
subcategory: null,
current: 0,
id: 0,
inputs: [],
categories: [],
subcategories: []
}
},
mounted() {
axios.get('/api/categories').then(res => {
this.categories = res.data
})
},
created() {
this.addRow()
},
methods: {
addRow() {
this.inputs.push({
category: '',
subcategory: '',
sku: '',
description: '',
image: ''
})
},
onFileChanged(event) {
this.selectedFile = event.target.files[0]
}
}
}
</script>
这是填充下拉菜单的第二个组件
<template>
<div class="border-0">
<div class="row">
<div class="col-md-8">
<div class="form-group ml-2">
<label class="gray-text-color font-montserrat-regular" :for="part">
{{ $t('labels.frontend.request.part') }} *
</label>
<div class="form-group brd3">
<select
:name="'r[' + index + '][category]'"
:id="category + index"
class="form-control light-gray-background arrow-select-position request-input"
v-model="input.category"
@change="onchangeCategorie"
required
>
<option :value="null" disabled selected>
{{ $t('labels.account.create.selectCategory') }}
</option>
<option
v-for="(option, index1) in categories"
:value="index1"
:key="index1"
>
{{ option }}
</option>
</select>
</div>
<div class="form-group brd3">
<select
:name="'r[' + index + '][subcategory]'"
:id="subcategory + index"
class="form-control light-gray-background arrow-select-position request-input"
v-model="input.subcategory"
required
>
<option :value="null" disabled selected>
{{ $t('labels.frontend.request.subCategory') }}
</option>
<option
v-for="(option, index1) in subcategories"
:value="index1"
:key="option.id"
>
{{ option }}
</option>
</select>
</div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="gray-text-color font-montserrat-regular" :for="sku">
{{ $t('labels.frontend.request.articleNumber') }}
</label>
<input
type="text"
:name="'r[' + index + '][sku]'"
:id="'sku' + index"
v-model="input.sku"
class="form-control light-gray-background request-input"
/>
</div>
</div>
</div>
<div class="row">
<div class="col-9">
<div class="form-group" style="margin-right:-40px">
<input
type="text"
:name="'r[' + index + '][description]'"
v-model="input.description"
class="form-control light-gray-background input-width-mobile request-input"
placeholder="Toelichting (optioneel)"
/>
</div>
</div>
<input
:id="'image' + index"
:name="'r[' + index + '][image]'"
type="file"
class="camera-button inputfile"
:change="input.image"
accept="image/*"
@change="onFileChanged"
/>
<label :for="'image' + index">
<img
src="../../../../../resources/assets/images/cameraIcon.png"
alt="Camera icon"
class="camera-button-position"
/>
</label>
<div class="pr-l-200 ft-14 mr-3">
<label>{{ $t('labels.frontend.request.image') }}</label>
</div>
<div id="preview">
<img v-if="url" :src="url" alt="no Image." />
<button
v-if="url != null"
type="button"
@click="url = null"
class="btn fa fa-trash btn-default bt-radius"
></button>
</div>
</div>
<button
type="button"
@click="deleteRow(index)"
class="btn btn-danger fa fa-trash bt-radius"
></button>
</div>
</template>
<script>
export default {
props: {
part: {
type: String,
default: null
},
sku: {
type: String,
default: null
},
description: {
type: String,
default: null
},
image: {
type: String,
default: null
},
index: {
type: Number,
default: 0
},
input: {
type: Object,
default: () => ({})
},
inputs: {
type: Array,
default: () => []
}
},
data() {
return {
test: null,
category: null,
selectedFile: null,
subcategory: null,
categories: [],
subcategories: [],
url: null
}
},
mounted() {
axios.get('/api/categories').then(res => {
this.categories = res.data
})
},
methods: {
deleteRow(index) {
console.log(index)
this.$delete(this.inputs, index)
},
onFileChanged(event) {
this.selectedFile = event.target.files[0]
this.input.image = this.selectedFile
this.url = URL.createObjectURL(this.selectedFile)
},
onchangeCategorie(e) {
axios.get('/api/categories/' + e.target.value).then(res => {
this.subcategories = res.data
})
}
}
}
</script>
<style>
#preview {
display: flex;
justify-content: center;
align-items: center;
margin: auto;
}
#preview img {
max-width: 200px;
max-height: 200px;
border-radius: 5px;
border: 1px solid lightgray;
}
</style>
当我尝试从上到下删除第一行或任何行时,所有子类别都消失了。 当我从下到上删除行时,效果很好
答案 0 :(得分:0)
您的问题是由以下事实引起的:您的行没有适当的稳定的唯一ID,而是在:key
指令中将其数组索引用作v-for
。这是有问题的原因,是当您使用.$delete()
从数组中删除一个元素时,所有后面的元素都向下移动到一个新的较低索引,从而使数组保持连续。
解决方案是给您的行一个唯一的ID。一个简单的全局计数器就可以了:
var counter = 0; // global counter for row IDs (or anything else that needs one)
export default {
// ...
methods: {
addRow() {
this.inputs.push({
category: '',
subcategory: '',
sku: '',
description: '',
image: '',
id: ++counter // this gives each row a distinct ID number
})
},
// ...
}
然后,您可以将此唯一ID用作:key
指令中的v-for
:
<li v-for="(input, index) in inputs" :key="input.id">
<request-part :index="index" :input="input" :inputs="inputs">
</request-part>
<hr />
</li>