之前用JS写过文件上传,现在改用Vue的方式重新写一遍,发现清爽多了。附上成品及代码。
成品:
代码:
组件名:Attachment,props只有一个:最大允许上传的附件数量。
<template>
<div class="attachment">
<div class="p-2 rounded">
<p class="mb-2">请选择图片上传: <span>(最多可上传{{ maxAttachmentsCount }}张图片)</span></p>
<div class="preview d-block float-left">
<div v-for="(file, index) in files" :key="`file_${index}`" class="pre-item mr-2">
<div class="cover rounded">
<img :src="file.src" />
</div>
</div>
</div>
<label :class="{ 'hidden-label': files.length >= parseInt(maxAttachmentsCount) }" class="d-flex align-items-center justify-content-center attachment-upload-area rounded bg-secondary border border-light mb-1">
<i class="fas fa-camera fa-3x" style="color: white;"></i>
<input type="file" class="d-none" @change="uploadAttachment">
</label>
</div>
</div>
</template>
<script>
import $ from 'jquery'
export default {
props: [ 'maxAttachmentsCount' ],
data() {
return {
files: []
}
},
methods: {
uploadAttachment(event) {
const file = $(event.target)[0]
if (file.files[0].type.indexOf('image/') === -1) {
alert('只能上传图片,请重新上传。')
return false
}
if (file.files[0] !== undefined) {
const reader = new FileReader()
reader.readAsDataURL(file.files[0])
reader.onloadend = (e) => {
this.files.push({ src: e.target.result })
}
this.$el.querySelector('label').appendChild(event.target.cloneNode(true))
}
}
}
}
</script>
<style scoped lang="scss">
.attachment {
margin-bottom: 1em;
.pre-item {
position: relative;
display: inline-block;
vertical-align: bottom;
}
.cover {
width: 80px;
height: 80px;
overflow: hidden;
img {
max-height: 80px;
width: auto;
clip: rect(200px 300px 300px 200px);
}
}
.attachment-upload-area {
height: 80px;
width: 80px;
}
}
.hidden-label {
visibility: hidden;
}
}
</style>
感觉没什么需要特别解释的。
over。