我有一个子组件,它有一个隐藏在开槽元素后面的输入字段。父级将提供带槽的点击事件元素,但也会显示文件的预览,并可以在上方删除它们。
我不确定在子/父关系之间工作时如何使用此选择和预览功能。
下面是我所得到的,但我现在对去哪里感到困惑。
该插槽用于触发子级中的事件,但在尝试实际按照当前编写的方式呈现事物时,我得到了 "TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'."
。
我哪里出错了?
如果您需要更多信息,请告诉我!加油!
注意:我还需要使其与 V-model 兼容,但我目前不知道如何做到这一点。
UploadMediaFiles(子组件)
<template>
<div class="upload-media-files">
<input
id="input-file"
type="file"
accept="*"
multiple
@change="addMedia"
class="_add-media-input"
ref="input"
/>
<label for="input-file">
<slot :openFileDialog="openFileDialog">
<img
src="https://www.clipartmax.com/png/middle/142-1422132_png-file-svg-upload-file-icon-png.png"
alt=""
/>
</slot>
</label>
</div>
</template>
<style lang="sass" scoped>
input
display: none
</style>
<script>
export default {
name: 'UploadMediaFiles',
props: {
multiple: { type: Boolean },
accept: { type: String },
},
data() {
return {
files: [],
}
},
computed: {},
methods: {
async addMedia(event) {
const files = event.target.files || event.dataTransfer.files
if (!files.length) return
console.log(`files → `, files)
this.files.push(files)
this.$emit('selected', this.files)
},
openFileDialog() {
this.$refs.input.click()
},
},
}
</script>
SelectAndPreviewFiles(父组件)
<template>
<div class="select-and-preview-files">
<div v-if="selectedFiles">
<div :key="index" v-for="(selectedFile, index) in selectedFiles">
<img :src="selectedFile" alt="" />
<button @click="deleteFile(index)">Delete</button>
</div>
</div>
<!-- <img />
//OR
<video /> -->
<!-- <img :src="selectedFile" alt="" />-->
<UploadMediaFiles @selected="(files) => selectFiles(files)" v-slot="{ openFileDialog }">
<button @click="openFileDialog">
<img
src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Circle-icons-upload.svg/1200px-Circle-icons-upload.svg.png"
alt=""
/>
</button>
</UploadMediaFiles>
</div>
</template>
<style lang="sass" scoped>
img
width: 20%
margin: auto
display: block
margin-bottom: 10px
</style>
<script>
import UploadMediaFiles from '../atoms/UploadMediaFiles.vue'
export default {
name: 'SelectAndPreviewFiles',
components: {
UploadMediaFiles,
},
props: {},
data() {
return {
selectedFiles: [],
}
},
computed: {},
methods: {
selectFiles(files) {
this.selectedFiles.push(files)
this.previewImage(files)
},
previewImage(files) {
var vm = this
for (var index = 0; index < files.length; index++) {
var reader = new FileReader()
reader.onload = function (event) {
const imageUrl = event.target.result
vm.files.push(imageUrl)
}
reader.readAsDataURL(files[index])
}
},
deleteFile(index) {
this.selectedFiles.splice(index, 1)
},
},
}
</script>
没有父子关系的 CodePen https://codepen.io/LovelyAndy/pen/gOmYGKO?editors=0001
答案 0 :(得分:1)
问题是多个选定文件的 input
值是一个 FileList
数组,它本身是一个 File
对象列表。但是,previewImage()
似乎假定该值是一个 File
对象数组。
files[index]
实际上是一个 FileList
,它不是 reader.readAsDataURL()
可接受的参数,从而导致错误。
要解决此问题,请迭代数组中的每个 FileList
:
export default {
methods: {
selectFiles(files) {
this.selectedFiles.push(files);
this.previewImage(files);
},
previewImage(files) {
var vm = this
for (var index = 0; index < files.length; index++) {
const fileList = files[index]
fileList.forEach(file => {
var reader = new FileReader()
reader.onload = function (event) {
const imageUrl = event.target.result
vm.selectedFiles.push(imageUrl)
}
reader.readAsDataURL(file)
})
}
},
}
}