Javascript 为什么在vue组件上输入另一个输入时,输入文件的值丢失?
我有两个组件 我的第一个组件(父组件)如下所示:Javascript 为什么在vue组件上输入另一个输入时,输入文件的值丢失?,javascript,vue.js,vuejs2,vue-component,vuex,Javascript,Vue.js,Vuejs2,Vue Component,Vuex,我有两个组件 我的第一个组件(父组件)如下所示: <template> <div> ... <form-input id="name" name="name" v-model="name">Name</form-input> <form-input id="birth-date" name="birth_date" type="date" v-model="birthDa
<template>
<div>
...
<form-input id="name" name="name" v-model="name">Name</form-input>
<form-input id="birth-date" name="birth_date" type="date" v-model="birthDate">Date of Birth</form-input>
<form-input id="avatar" name="avatar" type="file" v-on:triggerChange="onFileChange($event)">Avatar</form-input>
<form-input id="mobile-number" name="mobile_number" type="number" v-model="mobileNumber">Mobile Number</form-input>
...
</div>
</template>
<script>
export default {
data() {
return {
name: null,
birthDate: null,
mobileNumber: null
}
},
methods: {
onFileChange(e) {
let self = this
this.validate(e.target.files[0])
.then(function(res) {
let files = e.target.files,
reader = new FileReader()
// if any values
if (files.length) {
self.removeErrorMessageUpload()
self.files = files[0]
reader.onload = (e) => {
self.updateProfileAvatar(e.target.result)
}
reader.readAsDataURL(files[0])
}
})
.catch(function() {
// do something in the case where the image is not valid
self.displayErrorMessageUpload()
})
},
validate(image) {
let self = this
return new Promise(function(resolve, reject) {
// validation file type
if (!self.allowableTypes.includes(image.name.split(".").pop().toLowerCase())) {
reject()
}
// validation file size
if (image.size > self.maximumSize) {
reject()
}
// validation image resolution
let img = new Image()
img.src = window.URL.createObjectURL(image)
img.onload = function() {
let width = img.naturalWidth,
height = img.naturalHeight
window.URL.revokeObjectURL(img.src)
if (width != 100 && height != 100) {
reject()
}
else {
resolve()
}
}
})
},
}
}
</script>
选择一个文件,然后键入名称。该文件将被重置。
名称
出生日期
阿凡达
手机号码
所以问题是:
在
中选择一个文件后,如果在
中键入内容,则
将擦除。为什么呢
这是因为编辑
时,Vue将“重新绘制”组件
当它重新绘制
时,它将返回到“Nothing selected”(未选择任何内容),因为它是一个新的
解决方案:保留文件的值
作为中的点,以标准方式在
的文件中
下面的代码就是这样做的。它监视值
属性(当父级使用v-model
时出现该属性,并将其值设置为
的.files
属性)
我们必须使用两个
(使用v-if
/v-else
),因为当它是
时,可以设置:value
属性,事件处理程序应该不同(@change=“$emit('input',$event.target.files)”
),我们希望保留一个ref
,以便设置文件
下面是完整的工作演示
Vue.component('form-input'{
模板:“#表单输入tpl”,
名称:“表单输入”,
道具:{
'id':字符串,
“名称”:字符串,
'isRequired':{type:Boolean,默认值:true},
'type':{type:String,默认值:'text'},
'value':{type:[字符串、数字、文件列表、数据传输]}
},
安装的(){
//在创建或更新时设置文件(如果父项的值更改)
此.$watch('value',()=>{
如果(this.type==“file”){this.$refs.inputFile.files=this.value;}
},{immediate:true});
}
});
新Vue({
el:“#应用程序”,
数据:{
名称:空,
出生日期:空,
mobileNumber:null,
文件:空
}
})
名称
出生日期
阿凡达
手机号码
“为什么输入类型文件的值丢失?”与前面的语句冲突,即@Mark Schultheis你是什么意思?我不明白你说的“如果我输入输入类型文件,文件的值将显示在输入类型文件中,但如果我输入输入类型文本,输入类型文件的值将丢失,为什么输入类型文件的值将丢失?”但是句子“但是如果我输入输入类型文本,输入类型文件的值将丢失”“这是什么意思?文本
类型字段正在影响文件
类型字段?如果一个字段影响另一个字段,则表明此处可能存在其他内容,这是毫无意义的。请注意,默认的html输入类型为type=“text”
如果未指定。可能会将呈现的HTML显示为附加信息。@markschultheis这显然是因为v-on:change=“applySelected($event)”
或@input=“$emit('input',$event.target.value)”
。它在输入类型文本、输入类型文件、输入类型日期和输入类型编号上运行。因为我将其合并为一个组件(在最新的浏览器中),所以设置输入[type=file]的文件
属性
到另一个文件列表。我不知道vue.js,所以我自己无法捕获渲染事件,也无法访问新的输入,只是为了让您知道它实际上是可行的。@Kaido humm,我实际上知道它是可以通过小故障或其他原因实现的。因为它是非标准的(至少不受v-model
支持)我认为这不值得追求。但是谢谢你告诉我们,在更新的浏览器中有一个标准的方法是个好消息!@acdcjunior没有其他方法吗?我正在使用必需的html5。如果使用你的方法,它将始终显示验证html5。以及我是否可以使用你的方法将所选文件发送到服务器端?嘿,伙计们,谢谢推动:)我结束了更多的研究,我认为最终版本是相当干净的!它使用标准界面设置.files
!没有黑客!在这个过程中我学到了很多!非常感谢!@成功者@Kaiido@acdcjunior不客气。我试试看。顺便说一句,你所说的立即:真是什么意思?
<template>
<div class="form-group">
<label :for="id" class="col-sm-3 control-label"><slot></slot></label>
<div class="col-sm-9">
<input :type="type" :name="name" :id="id" class="form-control" :value="value" v-on:change="applySelected($event)" @input="$emit('input', $event.target.value)">
</div>
</div>
</template>
<script>
export default {
name: "form-input",
props: {
'id': String,
'name': String,
'isRequired': {
type: Boolean,
default: true
},
'type': {
type: String,
default() {
if(this.type == 'number')
return 'number'
return 'text'
}
},
'value': {
type: [String, Number]
}
},
methods: {
applySelected(e) {
this.$emit('triggerChange', e)
}
}
}
</script>