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>