vue-quill-editor是一个简单实用的富文本编辑器(官网),内置提供quill-image-extend-module模块(地址)支持图片上传图片到服务器而不是生成base64,但是有个明显的缺陷是只能上传一张(即使不用这个插件也只能上传一张生成base64 =。=), 这是个明显缺陷,而且操作后台的运营肯定不干(我™辛辛苦苦整理好的商品详情图片列表你让我一个个上传?),所以还是要多图片上传还是要实现,请看下面代码:
基于vue-quill-editor 再做一次封装:
<template>
<div class="quill-editor-container">
<quill-editor
v-if="showEditor"
v-model="content"
:options="editorOption"
@change="onEditorChange($event)">
</quill-editor>
</div>
</template>
<script>
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import { quillEditor, Quill } from 'vue-quill-editor'
import { getUploadSign } from "@/api/goods"
// 配置参照这里
// https://github.com/surmon-china/vue-quill-editor/blob/master/src/editor.vue
import toolbar from './toolbar'
const Delta = Quill.import('delta')
export default {
name: 'QuillEditor',
components: {
quillEditor
},
props: {
value: {
type: String,
default: '',
}
},
data () {
return {
showEditor: false,
imgSign: {},
content: this.value || '',
editorOption: {}
}
},
watch: {
value(val) {
this.content = val
},
},
mounted () {
this.getImgSign()
},
methods: {
// 获取图片上传签名(因为上传到腾讯云,所以要一些额外参数)
getImgSign() {
getUploadSign().then(({ data }) => {
this.imgSign = data
this.setEditorOption()
})
},
// 设置配置信息
setEditorOption() {
// 当前组件实例
let vm = this
this.editorOption = Object.assign(this.editorOption, {
placeholder: '请插入内容...',
modules: {
toolbar: {
container: toolbar,
handlers: {
// 自定义上传图片到服务器
image: function() {
// quill插件实例
let _self = this
// 创建上传文件input并触发
let fileInput = document.createElement('input')
fileInput.setAttribute('type', 'file')
fileInput.setAttribute('multiple', 'multiple')
fileInput.setAttribute('accept', 'image/*')
fileInput.addEventListener('change', () => {
if (fileInput.files !== null) {
const files = Array.from(fileInput.files).reverse()
// 利用es6迭代器异步顺序上传图片,保证图片插入顺序正常
const it = files[Symbol.iterator]()
uploadFile()
function uploadFile () {
const { done, value: _file } = it.next()
if (done) return
let reader = new FileReader()
reader.onload = (event) => {
const range = _self.quill.getSelection(true)
// 设置图片上传地址
const uploadImgServer = 'https://upload.chujiayoupin.com/v1/upload/file'
// 创建formData参数提交(文件+签名信息)
const formData = new FormData()
formData.append('file', _file)
for (const [key, val] of Object.entries(vm.imgSign)) {
formData.append(key, val)
}
// 发送图片上传请求
const xhr = new XMLHttpRequest()
xhr.open('POST', uploadImgServer)
xhr.timeout = 6000
xhr.ontimeout = () => {
alert('图片上传超时')
}
xhr.onreadystatechange = () => {
let result
if (xhr.readyState === 4) {
// http status code
if (xhr.status < 200 || xhr.status >= 300) {
return alert(`上传图片发生错误,上传图片发生错误,服务器返回状态是 ${xhr.status}`)
}
result = xhr.responseText
if (typeof result !== 'object') {
try {
result = JSON.parse(result)
} catch {
return alert('上传图片失败', '上传图片返回结果错误,返回结果是: ' + result)
}
}
// 根据服务器返回的结果自行拼接图片地址
const URI = result.data.items.file.map(v => `https://img.chujiayoupin.com${v.filename}`)[0]
// 插入到文本
_self.quill.updateContents(
new Delta()
.retain(range.index)
.delete(range.length)
.insert({ image: URI })
)
}
// 上传下一个图片
uploadFile()
}
xhr.send(formData)
}
reader.readAsDataURL(_file)
}
}
})
fileInput.click()
}
}
}
}
})
this.$nextTick(() => {
this.showEditor = true
})
},
// 文本改变后同步回父组件绑定的值
onEditorChange(event) {
this.$emit('input', event.html)
}
}
}
</script>
// 设定编辑器高度
<style lang="less" scoped>
.quill-editor /deep/ .ql-container {
height: 360px;
}
</style>
父组件引入
<QuillEditor v-model="xxx" />
这样就OK啦(*^__^*) ……