富文本vue-quill-editor结合el-element实现自定义上传组件
需求一 图片上传
就是要一个富文本编辑器,然后有图片上传功能,因为vue-quill-editor是将图片转为base64编码,所以当图片比较大时,提交后台时参数过长,导致提交失败。
解决思路
将图片先上传至服务器,再将图片链接插入到富文本中 图片上传的话可以使用element或者iview,这里我以iview举例 图片上传区域要隐藏,自定义vue-quill-editor的图片上传,点击图片上传时调用iview或者element的图片上传,上传成功后在富文本编辑器中显示图片
步骤
零、安装使用
npm install vue-quill-editor --save
main.js
import VueQuillEditor from 'vue-quill-editor'
Vue.use(VueQuillEditor);
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
一、自定义vue-quill-editor图片上传
html:
<quill-editor
v-model="content"
:options="editorOption"
ref="QuillEditor">
</quill-editor>
js:
<script>
// 工具栏配置
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{'header': 1}, {'header': 2}], // custom button values
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
[{'direction': 'rtl'}], // text direction
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{'color': []}, {'background': []}], // dropdown with defaults from theme
[{'font': []}],
[{'align': []}],
['link', 'image', 'video'],
['clean'] // remove formatting button
export default {
data () {
return {
content: '',
editorOption: {
modules: {
toolbar: {
container: toolbarOptions, // 工具栏
handlers: {
'image': function (value) {
if (value) {
alert('自定义图片')
} else {
this.quill.format('image', false);
</script>
二、调用element或iview图片上传组件
html:
<Upload
:show-upload-list="false"
:on-success="handleSuccess"
:format="['jpg','jpeg','png','gif']"
:max-size="2048"
multiple
action="/file/upload"
<Button icon="ios-cloud-upload-outline" ></Button>
</Upload>
<quill-editor
v-model="content"
:options="editorOption"
ref="QuillEditor">
</quill-editor>
css:
.ivu-upload {
display: none;
}
js:
data () {
return {
content: '',
editorOption: {
modules: {
toolbar: {
container: toolbarOptions, // 工具栏
handlers: {
'image': function (value) {
if (value) {
// 调用iview图片上传
document.querySelector('.ivu-upload .ivu-btn').click()
} else {
this.quill.format('image', false);
methods: {
handleSuccess (res) {
// 获取富文本组件实例
let quill = this.$refs.QuillEditor.quill
// 如果上传成功
if (res) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片,res为服务器返回的图片链接地址
quill.insertEmbed(length, 'image', res)
// 调整光标到最后
quill.setSelection(length + 1)
} else {
// 提示信息,需引入Message
Message.error('图片插入失败')
}
三、假如需要多个富文本编辑器
可能不止一处地方用到,比如添加完成后还有编辑功能,那就复制一份文件上传和富文本编辑:两个富文本用不同的ref标记,在各自配置中调用各自的文件上传;文件上传成功也使用不同的方法名称,里面调用各自的富文本编辑器。
重点: 富文本和文件上传不管使用类名还是什么方式区分的,这两处地方都要和之前区分开。
需求二 文件上传
和图片上传相同,不同的是上传文件。解决的思路也相同:在vue-quill-editor中自定义按钮,点击使用iView的文件上传,然后将地址赋值给a标签的href属性,插入到富文本光标处。
步骤
一、自定义编辑器附件上传
我想通过download属性自定义文件下载名称,但是两种方式都失败了,可以忽略相关代码。以下是为富文本自定义插入a链接
import { Quill } from 'vue-quill-editor';
// 自定义插入a链接
var Link = Quill.import('formats/link');
class FileBlot extends Link { // 继承Link Blot
static create(value) {
let node = undefined
if (value&&!value.href){ // 适应原本的Link Blot
node = super.create(value);
else{ // 自定义Link Blot
node = super.create(value.href);
// node.setAttribute('download', value.innerText); // 左键点击即下载
node.innerText = value.innerText;
node.download = value.innerText;
return node;
FileBlot.blotName = 'link';
FileBlot.tagName = 'A';
Quill.register(FileBlot);
配置工具栏,添加了一个
upload
,其余不需要的都可以去掉
<script>
// 自定义插入a链接
// ...
// 工具栏配置
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{'header': 1}, {'header': 2}], // custom button values
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
[{'direction': 'rtl'}], // text direction
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{'color': []}, {'background': []}], // dropdown with defaults from theme
[{'font': []}],
[{'align': []}],
['link', 'image', 'upload'],
['clean'] // remove formatting button
export default {
data () {
return {
content: '',
editorOption: {
modules: {
toolbar: {
container: toolbarOptions, // 工具栏
handlers: {
'image': ((value) => {
if (value) {
alert('自定义图片')
} else {
this.quill.format('image', false);
'upload': ((value) => {
if (value) {
alert('自定义文件上传')
</script>
自定义文件上传的图标样式
.ql-snow.ql-toolbar .ql-upload{
background: url("../assets/images/icon-upload.svg");
background-size: 16px 16px;
background-position: center center;
background-repeat:no-repeat;
/*background: red;*/
}
二、调用element或iview上传组件
为两个图片上传分别定义了类名,以做调用时的区分。
<!-- 上传图片 -->
<Upload
:show-upload-list="false"
:on-success="handleSuccess"
:format="messageAllData.imgFileType"
:before-upload="handleBeforeUpload"
type="drag"
:action="api.imgManage"
class="uploadImage">
</Upload>
<!-- 上传文件 -->
<Upload :show-upload-list="false"
:on-success="handleFileSuccess"
:before-upload="handleFileBeforeUpload"
type="drag"
:action="api.imgManage"
class="uploadFile">
</Upload>
修改工具栏配置,当点击富文本时,调用相应的上传组件
handlers: {
'image': (value => {
if (value) {
document.querySelector('.uploadImage input').click()
}else {
this.quill.format('image', false);
'upload': (value => {
if (value) {
document.querySelector('.uploadFile input').click()
}
这两个文件上传都要隐藏
.uploadImage,
.uploadFile{
width: 0;
height: 0;
display: none;
}
下面是插入图片和文件的方法
<quill-editor
v-model="content"
:options="editorOption"
ref="QuillEditor">
</quill-editor>
methods: {
// 图片
handleSuccess (res, file) {
let quill = this.$refs.QuillEditor.quill
let length = quill.getSelection().index;
quill.insertEmbed(length, 'image', res)
quill.setSelection(length + 1)
// 文件
handleFileSuccess (res, file) {
let fileNameLength = file.name.length
// 插入链接
let quill = this.$refs.QuillEditor.quill
let length = quill.getSelection().index;
quill.insertEmbed(length, 'link', {href:res, innerText:file.name}, "api")
quill.setSelection(length + fileNameLength)
}
bug及优化
一、回车光标不显示
不知道为什么,百度都搜不到,好像只有我出现了这个问题,最后通过监听回车,手动换行并在换行后加了一个空格,因为没有内容的时候光标不显示,然后把光标向前调一个位置,移到空格前面。
const bindings = {
custom: {
key: 13,
handler: function(range, context) {
this.quill.insertText(range.index, '\n ');
setTimeout(() => {
let nowRange = this.quill.getSelection().index - 1
this.quill.setSelection(nowRange)
}, 0)
export default {
data () {
return {
content: '',
editorOption: {
modules: {
keyboard: {
bindings: bindings
toolbar: {
// ...
}
二、给菜单栏添加中文标题title
// 标题
const titleConfig = {
'ql-bold':'加粗',
'ql-color':'颜色',
'ql-font':'字体',
'ql-code':'插入代码',
'ql-italic':'斜体',
'ql-link':'添加链接',
'ql-background':'背景颜色',
'ql-size':'字体大小',
'ql-strike':'删除线',
'ql-script':'上标/下标',
'ql-underline':'下划线',
'ql-blockquote':'引用',
'ql-header':'标题',
'ql-indent':'缩进',
'ql-list':'列表',
'ql-align':'文本对齐',
'ql-direction':'文本方向',
'ql-code-block':'代码块',
'ql-formula':'公式',
'ql-image':'图片',
'ql-video':'视频',
'ql-clean':'清除字体样式',
'ql-upload':'文件'
methods: {
addQuillTitle () {
const oToolBar = document.querySelector('.ql-toolbar'),
aButton = oToolBar.querySelectorAll('button'),
aSelect = oToolBar.querySelectorAll('select');
aButton.forEach(function(item){
if(item.className === 'ql-script'){
item.value === 'sub' ? item.title = '下标': item.title = '上标';
}else if(item.className === 'ql-indent'){
item.value === '+1' ? item.title ='向右缩进': item.title ='向左缩进';
}else{
item.title = titleConfig[item.classList[0]];
aSelect.forEach(function(item){
item.parentNode.title = titleConfig[item.classList[0]];
mounted () {
this.addQuillTitle()
},
有个需要注意的地方,按上面的方法使用后,确实有效,但是字体颜色和背景颜色的提示都变成了背景颜色,然后修改了标题栏的配置,提示才彼此对应。
const toolbarOptions = [
[{'color': []}, {'background': []}],
]
修改为
const toolbarOptions = [
[{'color': []}],
[{'background': []}],
]
页面展示
图片样式限制宽高和边距就可以了,在富文本编辑器里面可以回车换行;
可以另写一个
style标签
里面写上样式,也可以在原有的样式中通过深度选择器来写样式
<div v-html="editorContent" class="richTextStyle"></div>
<style>
/*富文本图片样式 */
.richTextStyle img {
max-width: 720px;
margin:10px;
/*富文本文字溢出不换行样式 */
.richTextStyle p, .richTextStyle sup, .richTextStyle strong,
.richTextStyle em, .richTextStyle u,
.richTextStyle s, .richTextStyle blockquote,
.richTextStyle h1, .richTextStyle h2, .richTextStyle h3,
.richTextStyle h4, .richTextStyle h5, .richTextStyle h6,