如何通过Vue实现图片的上传和预览?

1.前言

在现代互联网应用中,图片上传和预览功能已经成为必备的功能之一。本文将通过Vue实现图片上传和预览的功能,使得用户可以上传并查看一个或多个图片。实现此功能可以使用Vue插件 Vue-Croppa。Vue-Croppa提供了一个简单的方法使用Vue来上传和裁剪(可选)图片。它基于组件的模式开发,使得我们可以很方便地使用并自定义它。

2.安装

使用npm安装Vue-Croppa,可以使用以下命令安装:

npm install vue-croppa --save

接下来,在main.js文件中,我们需要将其导入我们的Vue实例。

import VueCroppa from 'vue-croppa'

import 'vue-croppa/dist/vue-croppa.css'

Vue.use(VueCroppa)

3.组件创建

我们需要创建一个组件来实现图片上传和预览的功能。Vue-Croppa提供了提供croppa组件来处理上传和裁剪。我们可以像下面一样在组件中使用Cropper:

<template>

<div>

<Cropper ref="cropper" :width="200" :height="200" :placeholder="'Upload your picture'" v-model="myAvatar"></Cropper>

</div>

</template>

在这个组件中,cropper可以使用ref标识元素。我们还可以设置其宽度和高度,并为其提供占位符。

4.图片上传

4.1 图片上传功能实现

通过Vue-Croppa实现的 图片上传 功能会自动捕获所选文件的“change”事件(当我们选择了文件时)。上传时,请调用cropper的upload()方法。此方法将返回一个Promise,其中resolve()会在文件上传成功后调用,reject()则会在文件上传失败时调用。

添加按钮,来触发图片上传功能:

<template>

<div>

<Cropper ref="cropper" :width="300" :height="300" v-model="myAvatar"></Cropper>

<div>

<button @click="submitAvatar()">Submit</button>

<input ref="fileInput" type="file" accept="image/*" style="display:none;" @change="selectFile">

</div>

</div>

</template>

在这里我们使用了一个input标签,并将其隐藏,然后通过控制代码触发它的点击事件。

<script>

export default {

name: 'App',

data: () => ({

myAvatar: null

}),

methods: {

submitAvatar () {

this.$refs.cropper.upload()

.then(() => {

console.log('Upload successful')

})

.catch(() => {

console.log('Upload failed')

})

},

selectFile () {

this.$refs.cropper.image = this.$refs.fileInput.files[0]

}

}

}

</script>

4.2 图片上传功能添加进度条

我们可以添加一个进度条,让用户更直观地看到上传的进度。

在本质上,我们可以使用XMLHttpRequest对象来向服务器发送请求。查看文件上传进度,我们还可以使用XMLHttpRequestUpload对象。实际上,XMLHttpRequestUpload对象公开了一些事件,用于跟踪上传的进度和状态。

我们将使用XMLHttpRequestUpload中的progress事件,该事件在上传期间接收文件上传进度的更新。实现代码如下:

<template>

<div>

<Cropper ref="cropper" :width="300" :height="300" v-model="myAvatar"></Cropper>

<div>

<button @click="submitAvatar()">Submit</button>

<input ref="fileInput" type="file" accept="image/*" style="display:none;" @change="selectFile">

<div v-if="progress">

<progress :max="fileSize" :value="progress"></progress>

</div>

</div>

</div>

</template>

<script>

export default {

name: 'App',

data: () => ({

myAvatar: null,

progress: 0,

fileSize: null

}),

methods: {

submitAvatar () {

if (this.myAvatar) {

this.fileSize = this.myAvatar.size

this.$refs.cropper.upload()

.then(() => {

console.log('Upload successful')

})

.catch(() => {

console.log('Upload failed')

})

}

},

selectFile () {

this.$refs.cropper.image = this.$refs.fileInput.files[0]

}

},

mounted () {

const xhr = new XMLHttpRequest()

xhr.upload.addEventListener('progress', (event) => {

const percent = event.loaded / this.fileSize * 100

this.progress = Math.round(percent)

})

}

}

</script>

在mounted钩子中,我们创建了XMLHttpRequest对象,并使用其upload属性添加EventListener进行监听。我们在`event.loaded / this.fileSize * 100`计算上传进度,并将计算结果设置为数据模型progress的值,以显示在页面上的进度条上。

5.图片预览

我们添加一个方法,在cropper.upload() resolved时调用,来显示所上传文件的缩略图。

<template>

<div>

<Cropper ref="cropper" :width="300" :height="300" v-model="myAvatar" @upload-success="handleSuccess"></Cropper>

<div>

<button @click="submitAvatar()">Submit</button>

<input ref="fileInput" type="file" accept="image/*" style="display:none;" @change="selectFile">

<div v-if="progress">

<progress :max="fileSize" :value="progress"></progress>

</div>

<div v-if="preview">

<img :src="preview" alt="Avatar" style="max-height:300px">

</div>

</div>

</div>

</template>

<script>

export default {

name: 'App',

data: () => ({

myAvatar: null,

progress: 0,

fileSize: null,

preview: null

}),

methods: {

submitAvatar () {

if (this.myAvatar) {

this.fileSize = this.myAvatar.size

this.$refs.cropper.upload()

.then(() => {

console.log('Upload successful')

})

.catch(() => {

console.log('Upload failed')

})

}

},

selectFile () {

this.$refs.cropper.image = this.$refs.fileInput.files[0]

},

handleSuccess (newValue) {

if (newValue) {

this.preview = URL.createObjectURL(newValue)

}

}

},

mounted () {

const xhr = new XMLHttpRequest()

xhr.upload.addEventListener('progress', (event) => {

const percent = event.loaded / this.fileSize * 100

this.progress = Math.round(percent)

})

}

}

</script>

我们添加了一个新的数据模型preview来保存新图像。然后,在Cropper组件上添加一个名为handleSuccess方法,在myAvatar数据模型更新时触发它。在这里,我们使用URL.createObjectURL方法生成模型的缩略图URL。

6.总结

本文详细介绍了如何使用Vue-Croppa和Vue来实现图片上传和预览功能。我们使用Vue-Croppa组件,实现了文件上传的功能,并将progress事件监听绑定到在mounted钩子中创建的XMLHttpRequest对象上,来显示上传的进度。最后,我们使用URL.createObjectURL方法来生成上传图片的缩略图URL,获取图片预览效果。