前言
最近的工作当中发现有这么一个需求,富文本编辑器图片上传需要按照选择顺序批量上传图片,因为项目应用的是 ElementUI,所以理所当然地会应用到里面的上传(el-upload),但是经过调试发现,并不满足此类型需求,
实现思路
1.针对使用el-upload的上传使用
2.针对原生input的上传使用
el-upload
废话不多说,先丢代码出来
<template>
<div>
<quill-editor
ref="quill-editor"
v-model="content"
:options="options"
@change="onEditorChange($event)"
style="width:100%;height:100%;" />
<el-upload
class="upload-col"
:show-file-list="false"
auto-upload
:accept="accept"
action="" multiple
:http-request="fileUpload"
:before-upload="beforeUpload">
<i class="quill-editor__uploadBtn"></i>
</el-upload>
</div>
</template>
<script>
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import {
quillEditor
} from 'vue-quill-editor'
/**
* 富文本
* content 内容
* options 参数配置
* uploadImageParam 上传图片的参数
*
*/
export default {
props: {
content: {
type: String,
required: true
},
options:{
type:Object,
default:()=>{
return {
placeholder: "请输入内容",
modules: {
toolbar: {
container: [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{
'header': 1
}, {
'header': 2
}],
[{
'list': 'ordered'
}, {
'list': 'bullet'
}],
[{
'script': 'sub'
}, {
'script': 'super'
}],
[{
'indent': '-1'
}, {
'indent': '+1'
}],
[{
'direction': 'rtl'
}],
[{
'size': ['small', false, 'large', 'huge']
}],
[{
'header': [1, 2, 3, 4, 5, 6, false]
}],
[{
'color': []
}, {
'background': []
}],
[{
'font': []
}],
[{
'align': []
}],
['link', 'image', 'video'],
['clean']
],
handlers: {
'image': function (value) {
if (value) {
document.querySelector('.quill-editor__uploadBtn').click()
} else {
this.quill.format('image', false);
}
}
}
}
}
}
}
},
uploadImageParam:{
type:Object,
default:()=>{
return {}
}
}
},
components: {
quillEditor
},
data() {
return {
accept: 'image/*',
imageTypes: ['jpg', 'jpeg', 'png', 'gif']
}
},
methods: {
fileUpload(fileobj) {
let param = new FormData()
param.append('file', fileobj.file)
for (let key in this.uploadImageParam) {
param.append(key, this.uploadImageParam[key])
}
this.$http.uploadImage(param).then(({ data }) => {
if (data.code === 200) {
const quill = this.$refs['quill-editor'].quill
,length = quill.getSelection().index
quill.insertEmbed(length, 'image', data.rows)
quill.setSelection(length + 1)
}
}).catch(err => {
this.$message.error('上传图片失败!请重新上传')
})
},
beforeUpload(file) {
const imageTypes = this.imageTypes
let isImage = false
for (let item of imageTypes) {
if (file.name.includes(item)) {
isImage = true
}
}
if (!isImage) {
this.$message.warning(`请上传格式为${imageTypes.join('、')}的图片!`)
return Promise.reject()
}
return true
},
onEditorChange({ html }) {
this.$emit('update:content', html)
}
}
}
</script>
<style lang="scss" scoped>
.upload-col{
height: 0;
width: 0;
overflow: hidden;
}
</style>
http-request 获取的参数只有一个 params,里面装载的只有每一次上传到临时保存区的单个文件的信息,当批量选择时每次上传临时区成功时都会调用,会导致的问题 你上传图片1、图片2、图片3 最后的上传结果可能会变成图片 1、图片 3、图片 2,这个可能和图片的实体大小有关,有可能因为实体大小问题导致上传到服务器请求回url的速度不一,所以有的图片上传更快地完成,所以有就有上传顺序的问题情况。
此处是已封装代码
调用方式
// html
<quill-editor
:content.sync="form.goodsDetail"
:uploadImageParam="editorUploadImageData"
/>
import quillEditor from '@/components/quill-editor'
components: {
quillEditor
},
原生input
返璞归真试试原生
<template>
<div>
<quill-editor
ref="quill-editor"
v-model="content"
:options="options"
@change="onEditorChange($event)"
style="width:100%;height:100%;" />
<div class="upload-col">
<input
class="quill-editor__uploadBtn"
style="display: none !important;"
@change="uploadSuccess"
multiple="multiple"
accept="image/jpeg, image/jpg, image/png"
type="file"
ref="referenceUpload"
>
</div>
</div>
</template>
<script>
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import {
quillEditor
} from 'vue-quill-editor'
/**
* 富文本
* content 内容
* options 参数配置
* uploadImageParam 上传图片的参数
*
*/
export default {
props: {
content: {
type: String,
required: true
},
options:{
type:Object,
default:()=>{
return {
placeholder: "请输入内容",
modules: {
toolbar: {
container: [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{
'header': 1
}, {
'header': 2
}],
[{
'list': 'ordered'
}, {
'list': 'bullet'
}],
[{
'script': 'sub'
}, {
'script': 'super'
}],
[{
'indent': '-1'
}, {
'indent': '+1'
}],
[{
'direction': 'rtl'
}],
[{
'size': ['small', false, 'large', 'huge']
}],
[{
'header': [1, 2, 3, 4, 5, 6, false]
}],
[{
'color': []
}, {
'background': []
}],
[{
'font': []
}],
[{
'align': []
}],
['link', 'image', 'video'],
['clean']
],
handlers: {
'image': function (value) {
if (value) {
document.querySelector('.quill-editor__uploadBtn').click()
} else {
this.quill.format('image', false);
}
}
}
}
}
}
}
},
uploadImageParam:{
type:Object,
default:()=>{
return {}
}
}
},
components: {
quillEditor
},
methods: {
uploadSuccess (e) {
const that = this
const getImages = async _ => {
let f = function (i) {
let param = new FormData()
param.append('file', e.target.files[i])
for (let key in that.uploadImageParam) {
param.append(key, that.uploadImageParam[key])
}
return that.$http.uploadImage(param).then(({ data }) => {
if (data.code === 200) {
const quill = that.$refs['quill-editor'].quill
,length = quill.getSelection().index
quill.insertEmbed(length, 'image', data.rows)
quill.setSelection(length + 1)
}
}).catch(err => {
console.log(err)
})
}
for (let i = 0; i < e.target.files.length; i++) {
await f(i)
}
this.$refs.referenceUpload.value = null
}
getImages()
},
onEditorChange({ html }) {
this.$emit('update:content', html)
}
}
}
</script>
<style lang="scss" scoped>
.upload-col{
height: 0;
width: 0;
overflow: hidden;
}
</style>
在 change 钩子的回调里(event.target.files)就是我们想要获取到的每一次选择的文件/图片列表,然后针对列表进行处理,还就就是input的样式的时候花了点时间,来回去对比el-upload的样式和自己写的原生样式区别。用法一致