添加文件选择组件
This commit is contained in:
190
src/components/FileUpload.vue
Normal file
190
src/components/FileUpload.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<docs>
|
||||
|
||||
## $emit
|
||||
|
||||
### @changed
|
||||
|
||||
```javascript
|
||||
{
|
||||
count: Number,
|
||||
min: Number,
|
||||
max: Number,
|
||||
multiple: Boolean,
|
||||
list: FileList,
|
||||
}
|
||||
```
|
||||
|
||||
### @exceeded
|
||||
|
||||
```javascript
|
||||
{
|
||||
count: Number,
|
||||
min: Number,
|
||||
max: Number,
|
||||
}
|
||||
```
|
||||
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<div class="file-upload" @click="selectFile()">
|
||||
<slot />
|
||||
<input
|
||||
ref="inputFile"
|
||||
class="input-file"
|
||||
type="file"
|
||||
:accept="accept == '' ? false : accept"
|
||||
:capture="capture == '' ? false : capture"
|
||||
:multiple="multiple"
|
||||
:name="name == '' ? false : name"
|
||||
@change="fileChanged()"
|
||||
@click.stop
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FileUpload',
|
||||
props: {
|
||||
|
||||
/**
|
||||
* 接受的文件类型
|
||||
* 格式与 input 标签的 accept 属性相同
|
||||
*/
|
||||
accept: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
/** 格式与 input 标签的 capture 属性相同 */
|
||||
capture: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
|
||||
/** 是否禁用 */
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/** 最大文件数量 */
|
||||
filesMax: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
|
||||
/** 最小文件数量 */
|
||||
filesMin: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
|
||||
/** 是否为多选 */
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
/** 为 input 设置 name */
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
logPrefix: '[文件上传]',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
||||
/** 选择了新的文件 */
|
||||
fileChanged() {
|
||||
|
||||
/** @type {HTMLInputElement} */
|
||||
const el = this.$refs['inputFile'];
|
||||
|
||||
/** @type {FileList} */
|
||||
var files = null;
|
||||
var count = 0;
|
||||
|
||||
const max = this.filesMin;
|
||||
const min = this.filesMax;
|
||||
|
||||
if (el) {
|
||||
files = el.files;
|
||||
count = files.length;
|
||||
} else {
|
||||
console.error(this.logPrefix, 'input 元素不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
console.warn(this.logPrefix, '未选择文件');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.multiple && min != 0 && max != 0) {
|
||||
if (max < min) {
|
||||
console.error(this.logPrefix, '文件数量限制设置错误');
|
||||
return;
|
||||
}
|
||||
if (count < min || count > max) {
|
||||
// 触发父组件 @exceeded
|
||||
this.$emit('exceeded', { count, min, max });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 触发父组件 @changed
|
||||
this.$emit('changed', {
|
||||
count,
|
||||
min,
|
||||
max,
|
||||
multiple: this.multiple,
|
||||
list: files,
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/** 选择文件 */
|
||||
selectFile() {
|
||||
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @type {HTMLInputElement} */
|
||||
const el = this.$refs['inputFile'];
|
||||
|
||||
if (el) {
|
||||
el.value = '';
|
||||
el.click();
|
||||
} else {
|
||||
console.error(this.logPrefix, 'input 元素不存在');
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.file-upload {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input-file {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user