处理VueJS组件中输入文件中的事件



我有一个子组件的banch,我想在其中更改图像:

<template>
<div>
<div>
<form enctype="multipart/form-data">
<input type="file" name="file" id="file" @change="change_file" class="py-6 px-8 hidden">
<label for="file" class="flex flex-col items-center text-main-color text-sm py-2 px-4">
<span class="text-sm mt-2" style="color: #7eaeb7;">Click to change image</span>
<img :src="'/img/'+data.img" alt="" class="w-48 h-48 mx-auto p-4" >
</label>
</form>
</div>
<div class="flex flex-col items-center">
<span class="">{{data.definition}}</span>
<span>{{data.description}}</span>
<div @click="edit_statment">
<span>Edit Statment</span>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['data'],
methods: {
change_image(event) {
let formData = new FormData();
formData.append('file', event.target.files[0]);
axios.post('/change_image', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
this.$emit('changeStatmentImg', response.data.new_image);
})
},
edit_statment() {
this.$emit('editStatment');
}
}
}
</script>

我在父组件上列出事件:

<template>
<div class="">
<statment v-for="item in statments" :key="item.id" :data="item" @editStatment="initialize(item, 'statment')" @changeStatmentImg="changeImage($event, item, 'statment')"></pr_course_statment>
</div>
</template>
<script>
export default {
data() {
return {
statments: [
{
img: 'module1.svg',
definition: 'First statment',
description: 'First statment description',
},
{
img: 'module2.svg',
definition: 'Second statment',
description: 'Second statment description',
},
{
img: 'module3.svg',
definition: 'Third statment',
description: 'Third statment description',
},
],
}
},
methods: {
initialize(item, model_name) {
console.log('item.id: ', item.id);  
},
changeImage(file_name, item, model_name) {
console.log(file_name);
console.log(item.id); 
console.log(model_name);
},
}
}
</script>

当我从组件发出事件时,在普通编辑文本字段的(初始化方法(的情况下,一切都很顺利

但是当子组件在"上暴露事件时;输入文件@change";每次时,它只使用Statments列表中的第一个项目

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<div id="app" class="flex justify-between">
<div v-for="item in statments">
<div class="flex flex-col items-center">
<div class="flex flex-col items-center border border-indigo-200 rounded-md">
<form class="flex justify-center my-4" enctype="multipart/form-data">
<input type="file" name="file" id="file" @change="changeImage(item)" class="py-6 px-8 hidden">
<label for="file" class="flex flex-col items-center text-main-color text-sm py-2 px-4">
<span class="text-sm mt-2" style="color: #7eaeb7;">Click to change image</span>
<img :src="item.img" alt="" class="w-48 h-48 mx-auto p-4" >
</label>
</form>
</div>
<div class="mt-4 mb-6" @click="changeStatment(item)" class="flex flex-col items-center">
<span>{{item.definition}}</span>
<span class="text-indigo-500 inline-flex items-center md:mb-2 lg:mb-0 main-color">Edit Statment
<svg class="w-4 h-4 ml-2" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M5 12h14"></path>
<path d="M12 5l7 7-7 7"></path>
</svg>
</span>
</div>
</div>  
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data() {
return {
statments: [
{
id: 1,
img: 'module1.svg',
definition: 'First statment',
description: 'First statment description',
},
{
id: 2,
img: 'module2.svg',
definition: 'Second statment',
description: 'Second statment description',
},
{
id: 3,
img: 'module3.svg',
definition: 'Third statment',
description: 'Third statment description',
},
],
}
},
methods: {
changeStatment(item) {
console.log('item.id: ', item.id);  
},
changeImage(item) {
console.log('item.id from form input: ', item.id);
},
}
})
</script>

我很确定,这是因为父组件中的:key="item.id",即undefined

:key-属性对于vue的内部渲染和缓存很重要,并且必须是全局唯一的(而不仅仅是THIS组件唯一的(

我总是用这样的东西:

<div v-for="(item, idx) in items" :key="`Items_${_uid}_${idx}`" />

_uid将随着渲染的每个vue组件而增加,因此它永远不会相同
idx需要区分该vue组件内部的元素(它们都在同一个vue组件内,因此具有相同的_uid(

最新更新