【发布时间】:2018-08-26 12:38:36
【问题描述】:
我有两个组件
我的第一个组件(父组件)是这样的:
<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>
从父组件调用子组件(表单输入组件)
我的子组件是输入类型文本、输入类型日期、输入类型文件和输入类型编号。我将它们全部组合成一个组件
子组件是这样的:
<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>
因为我合并到 1 个组件中,所以我遇到了一个新问题
如果我输入输入类型文件,文件的值将显示在输入类型文件中
但是如果我在输入类型文本中输入,输入类型文件的值丢失了
为什么输入类型文件的值不见了?
演示:
Vue.component('form-input', {
template: "#form-input-tpl",
name: "form-input",
props: {
'id': String,
'name': String,
'isRequired': {type: Boolean, default: true},
'type': { type: String, default () {if (this.type == 'number') {return 'number'} else {return 'text'}}},
'value': { type: [String, Number] }
},
methods: {
applySelected(e) { this.$emit('triggerChange', e) }
}
});
new Vue({
el: '#app',
data: {
name: null,
birthDate: null,
mobileNumber: null
},
methods: {
onFileChange(e) {
// ...
}
}
})
<script src="https://unpkg.com/vue"></script>
<template id="form-input-tpl">
<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>
<div id="app">
<h3>Select a file, then type a name. The file will be reset.</h3>
<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>
</div>
【问题讨论】:
-
"为什么输入类型文件的值丢失?"与之前的陈述冲突,即是?
-
@Mark Schultheiss 你什么意思?我不明白
-
你说“如果我输入输入类型文件,文件的值会显示在输入类型文件中但是如果我输入输入类型文本,输入类型文件的值丢失为什么值输入类型文件丢失?”但是那句“但是如果我在输入类型文本中输入,输入类型文件的值丢失”是什么意思?
text类型字段正在影响file类型字段?这是没有意义的,一个领域会影响另一个领域,这表明这里可能还有其他东西在起作用。请注意,如果未指定,则默认 html 输入类型为type="text"。 -
也许将呈现的 HTML 显示为附加信息。
-
@MarkSchultheiss 这显然是因为
v-on:change="applySelected($event)"或@input="$emit('input', $event.target.value)"。它在输入类型文本、输入类型文件、输入类型日期和输入类型编号上运行。因为我把它组合成一个组件
标签: javascript vue.js vuejs2 vue-component vuex