使用方法
不管vue-quill-editor对接的是那个UI框架,还是全部自己写,其实使用方法都是一样的。
- 首先都是先能将文件上传至七牛
- 然后针对vue-quill-editor开发handlers方法,触发上传功能,拿到回调值,insert进入富文本。
获取七牛token上传
region: 上传区域,可以设置为undefined
具体参数解释说明 参考文档,原文文档写得比较详细。
// 上传图片typescript
import { getQNToken } from '@/assets/api/QiNiu' // 已经写好的请求token接口
const qiniu = require('qiniu-js')
const QNUpload = (file: any, prefix: string, name: string, next) => {
return new Promise(async (resolve, reject) => {
const putExtra = {
fname: name,
params: {},
mimeType: null
}
const config = {
useCdnDomain: false // 是否使用 cdn 加速域名
}
// 接口getQNToken会缓存token到sessionStorage,发现没有重新请求
const token = sessionStorage.getItem('QNToken') || await getQNToken(***) // 获取token
const n = name.replace('.', '_' + new Date().getTime() + '.') // 重新命名
const key = prefix ? (prefix + '/' + n) : n // 加上传过来的前缀
const observable = qiniu.upload(file, key, token, putExtra, config) // 使用SDK方式发起请求
// next 是一个回调函数
observable.subscribe(next, (error) => {
reject(error)
}, (complete) => {
resolve(complete)
})
})
}
export default QNUpload
base64 to blob二进制
/**
* base64 to blob二进制
* @param {*} dataURI:string
*/
const dataURItoBlob = (dataURI) => {
const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
const byteString = atob(dataURI.split(',')[1])
const arrayBuffer = new ArrayBuffer(byteString.length)
const intArray = new Uint8Array(arrayBuffer)
for (let i = 0; i < byteString.length; i++) {
intArray[i] = byteString.charCodeAt(i)
}
return new Blob([intArray], { type: mimeString })
}
上传文件组件
<template>
<div class="upload">
<Icon type="md-add" />
<span v-show="width>0">{{width}} * {{height}}</span>
<input type="file" @change="uploadFile" :accept="mimeType"/>
<div class="progress" v-show="percent && percent !== 100">
<Progress :percent="percent" hide-info />
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue, Emit, Prop } from 'vue-property-decorator'
import { dataURItoBlob } from '@/assets/common'
import QNUpload from '@/assets/api/upload'
interface QNReceive {
type: string,
data: object
}
@Component
export default class Upload extends Vue {
// 上传路径前缀
@Prop(String) readonly prefix!: string
@Prop(String) readonly field!: string
// 控制文件上传大小
@Prop({ default: 1024 }) readonly size!: number
// 设置提示图尺寸
@Prop({ default: 200 }) readonly width!: number
@Prop({ default: 200 }) readonly height!: number
// 组件层控制上传类型,默认是图片
@Prop({ default: 'image/png, image/jpeg, image/gif, image/jpg' }) readonly mimeType!: string
// 已上传图片大小占比
percent:number = 0
@Emit()
uploadFile (e) {
const files = e.target.files
if (!files.length) return
let keys: Array<any> = []
for (let i = 0, len = files.length; i < len; i++) {
const file = files[i]
const size = this.size
// 大小验证
if (/image/g.test(file.type) && file.size / 1024 > size) {
this.$Message.info({ content: file.name + '大小不能超过' + size + 'KB', duration: 5 })
continue
}
// 读取文件转blob
const reader = new FileReader()
reader.addEventListener('load', (data: any) => {
const dataURI = data.target.result
const blob = dataURItoBlob(dataURI)
const name = file.name
const prefix = this.prefix
// 调取上传方法
QNUpload(blob, prefix, name, (next) => {
// 上传进度
this.percent = next.total.percent
}).then((data) => {
this.$emit('completeUpload', Object.assign(data, { field: this.field }))
}).catch(error => {
console.log(error)
})
})
reader.readAsDataURL(file)
}
}
}
</script>
<style lang="scss">
.upload {
width: 100%;
height: 80px;
position: relative;
border: 1px dashed #cccccc;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
i {
font-size: 40px;
cursor: pointer;
}
.progress {
position: absolute;
bottom: 2px;
left: 0;
width: 100%;
height: 20px;
}
span {
position: absolute;
bottom: 0;
left: 0;
display: block;
width: 100%;
height: 20px;
line-height: 20px;
color: $grayColor;
text-align: center;
font-weight: bold;
}
}
</style>
vue-quill-editor富文本添加上传图片
使用组件的方式加载富文本,配置toolbar,添加handlers处理方法。最后完成插入图片
这里只配置了一张一张图片上传,稍微改一下,添加multiple="true",就可以选中多个文件上传
<template>
<div>
<quill-editor style="height: 800px;" ref="myQuillEditor" v-model="Qcontent" :options="editorOption"></quill-editor>
<v-upload ref="upload" v-show="false" @completeUpload="getCompleteUpload" prefix="goodsDetail"></v-upload>
</div>
</template>
<script lang="ts">
import { Component, Vue, Emit, PropSync, Prop, Watch } from 'vue-property-decorator'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import { quillEditor } from 'vue-quill-editor'
import VUpload from '@/components/Upload.vue'
@Component({
components: {
quillEditor,
VUpload
}
})
export default class QuillEditor extends Vue {
@PropSync('content', { default: '' }) readonly Qcontent?: string
@Prop({ default: false }) readonly sendContent?: Boolean
@Watch('sendContent')
onSendContentChanged(val: boolean, oldVal: boolean) {
if (val) {
this.$emit('getContent', this.Quill.container.innerHTML)
}
}
QNHost = ****
Quill:any = ''
addRange: any = ''
uploadType = ''
editorOption = {
modules: {
toolbar: {
container: [
['bold', 'italic', 'underline'],
[{ 'header': 1 }, { 'header': 2 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'size': ['small', false, 'large', 'huge'] }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }],
[{ 'font': [] }],
[{ 'align': [] }],
['clean'],
// 新增image,使用自带的icon,添加新的handlers
['image']
],
handlers: {
// 点击 image会调取方法imgHandler
image: this.imgHandler
}
}
}
}
mounted () {
this.imgHandler()
}
@Emit()
imgHandler () {
const Quill: any = (this.$refs.myQuillEditor as Vue & {quill: () => any}).quill
this.Quill = Quill
const toolbar = Quill.getModule('toolbar')
const upload: any = this.$refs.upload
toolbar.addHandler('image', () => {
// 获取当前鼠标位置
this.addRange = Quill.getSelection()
// 触发上传,可以单独写input直接触发,这里使用封装的组件
upload.$el.getElementsByTagName('input')[0].click()
})
}
@Emit()
getCompleteUpload (data) {
const index = this.addRange.index || 0
// 上传成功拿到返回值,插入富文本
this.Quill.insertEmbed(index, 'image', this.QNHost + data.key)
}
}
</script>
总结
quill-editor 开发扩展还是很好开发的。
一直有个疑问就是:quill-editor自己整了一套数据接口delta,通过quill.getContents()获取到delta,这个delta怎么展示在没有引入这个包的界面上?
现在我的办法是:直接获取container的innerHTML
不知还有更好的办法没?