一·安装quill-editor插件
1.安装
npm install vue-quill-editor --save
2.创建设置文件
在components文件夹创建editor.vue文件
文件内容
<!-- 组件代码如下 -->
<template>
<div>
<script id="editor" type="text/plain"></script>
</div>
</template>
<script>
export default {
name: 'UE',
data() {
return {
editor: null
}
},
props: {
defaultMsg: {
type: String
},
config: {
type: Object
}
},
mounted() {
const _this = this;
this.editor = UE.getEditor('editor', this.config); // 初始化UE
this.editor.addListener("ready", function () {
_this.editor.setContent(_this.defaultMsg) // 确保UE加载完成后,放入内容。
});
},
methods: {
getUEContent() { // 获取内容方法
return this.editor.getContent()
}
},
destroyed() {
this.editor.destroy()
}
}
</script>
3.在页面中使用编辑器
<template>
<div>
<el-card style="height: 610px;">
<quill-editor v-model="content" ref="myQuillEditor" style="height: 500px;" :options="editorOption">
</quill-editor>
</el-card>
</div>
</template>
<script>
import {
quillEditor
} from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
export default {
name: 'FuncFormsEdit',
components: {
quillEditor
},
data() {
return {
content: null,
editorOption: {}
}
}
}
</script>
<style scoped>
</style>
4.以上就是简单的在vue+element-ui 使用富文本编辑器,效果图如下
二·自定义编辑器工具栏
1.在页面中设置组件
<template>
<div>
<el-card style="height: 610px;">
<quill-editor v-model="content" ref="myQuillEditor" style="height: 500px;" :options="editorOption">
<!-- 自定义toolar -->
<div id="toolbar" slot="toolbar">
<!-- Add a bold button -->
<button class="ql-bold" title="加粗">Bold</button>
<button class="ql-italic" title="斜体">Italic</button>
<button class="ql-underline" title="下划线">underline</button>
<button class="ql-strike" title="删除线">strike</button>
<button class="ql-blockquote" title="引用"></button>
<button class="ql-code-block" title="代码"></button>
<button class="ql-header" value="1" title="标题1"></button>
<button class="ql-header" value="2" title="标题2"></button>
<!--Add list -->
<button class="ql-list" value="ordered" title="有序列表"></button>
<button class="ql-list" value="bullet" title="无序列表"></button>
<!-- Add font size dropdown -->
<select class="ql-header" title="段落格式">
<option selected>段落</option>
<option value="1">标题1</option>
<option value="2">标题2</option>
<option value="3">标题3</option>
<option value="4">标题4</option>
<option value="5">标题5</option>
<option value="6">标题6</option>
</select>
<select class="ql-size" title="字体大小">
<option value="10px">10px</option>
<option value="12px">12px</option>
<option value="14px">14px</option>
<option value="16px" selected>16px</option>
<option value="18px">18px</option>
<option value="20px">20px</option>
</select>
<select class="ql-font" title="字体">
<option value="SimSun">宋体</option>
<option value="SimHei">黑体</option>
<option value="Microsoft-YaHei">微软雅黑</option>
<option value="KaiTi">楷体</option>
<option value="FangSong">仿宋</option>
<option value="Arial">Arial</option>
</select>
<!-- Add subscript and superscript buttons -->
<select class="ql-color" value="color" title="字体颜色"></select>
<select class="ql-background" value="background" title="背景颜色"></select>
<select class="ql-align" value="align" title="对齐"></select>
<button class="ql-clean" title="还原"></button>
<!-- You can also add your own -->
</div>
</quill-editor>
</el-card>
</div>
</template>
<script>
import {
Quill,
quillEditor
} from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
//引入font.css
import '../../../assets/css/font.css'
// 自定义字体大小
let Size = Quill.import('attributors/style/size')
Size.whitelist = ['10px', '12px', '14px', '16px', '18px', '20px']
Quill.register(Size, true)
// 自定义字体类型
var fonts = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif',
'宋体', '黑体'
]
var Font = Quill.import('formats/font')
Font.whitelist = fonts
Quill.register(Font, true)
export default {
name: 'FuncFormsEdit',
components: {
quillEditor
},
data() {
return {
content: null,
editorOption: {
placeholder: "请输入",
theme: "snow", // or 'bubble'
modules: {
toolbar: {
container: '#toolbar'
}
}
}
}
}
}
</script>
<style scoped>
</style>
2.引入自定义的字体文件
在 asset 文件夹下新建font.css 文件
文件内容
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
content: "宋体";
font-family: "SimSun";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
content: "黑体";
font-family: "SimHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
content: "微软雅黑";
font-family: "Microsoft YaHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
content: "楷体";
font-family: "KaiTi";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
content: "仿宋";
font-family: "FangSong";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
content: "Arial";
font-family: "Arial";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
content: "Times New Roman";
font-family: "Times New Roman";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
content: "sans-serif";
font-family: "sans-serif";
}
.ql-font-SimSun {
font-family: "SimSun";
}
.ql-font-SimHei {
font-family: "SimHei";
}
.ql-font-Microsoft-YaHei {
font-family: "Microsoft YaHei";
}
.ql-font-KaiTi {
font-family: "KaiTi";
}
.ql-font-FangSong {
font-family: "FangSong";
}
.ql-font-Arial {
font-family: "Arial";
}
.ql-font-Times-New-Roman {
font-family: "Times New Roman";
}
.ql-font-sans-serif {
font-family: "sans-serif";
}
3.更改后的效果
三·自定义编辑器图片上传
1.存在问题
vue-quill-editor 上传图片是将图片转为base64编码,当图片比较大时,提交到后台时参数过长会导致提交失败
解决办法:
把富文本内的图片动态上传到服务器,然后把图片加载到富文本编辑器。这样一来,图片标签内只需要存储图片的网络地址就可以了。
具体实现:
1.组件内调用element的upload组件和vue-quill-editor编辑器;
<template>
<div class="quill-editor">
<!-- 图片上传组件辅助,组件内添加v-show=“false”属性,把该组件隐藏起来。-->
<el-upload class="avatar-uploader" :action="uploadUrl" name="img" :show-file-list="false" :on-success="uploadSuccess" :before-upload="beforeUpload">
</el-upload>
<!--富文本编辑器组件-->
<quill-editor v-model="content" :options="editorOption" @blur="onEditorBlur($event)" @focus="onEditorFocus($event)" @ready="onEditorReady($event)" ref="QuillEditor">
</quill-editor>
<div v-html="content" />
</div>
</template>
2.在data函数内,设置upoad组件的图片上传接口地址;处理函数中匹配 image,定义富文本编辑器内的图片上传按钮点击事件,当点击上传图片图标时,触发 upoad 组件的图片上传事件;
handlers: {
image: function (value) {
if (value) {
// 调用element的图片上传组件
document.querySelector('.avatar-uploader input').click()
} else {
this.quill.format('image', false)
}
}
}
3.methods中,完善 upload图片上传成功事件。图片上传成功后,把图片加载到富文本编辑器内。
uploadSuccess (res) {
// 获取富文本组件实例
let quill = this.$refs.QuillEditor.quill
// 如果上传成功
if (res.code === 200 && res.data.url) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片,res.data.url为服务器返回的图片链接地址
quill.insertEmbed(length, 'image', res.data.url)
// 调整光标到最后
quill.setSelection(length + 1)
} else {
// 提示信息,需引入Message
this.$message.error('图片插入失败!')
}
}
四·编辑器图片大小可编辑和设置位置而且可以将图片拖拽到编辑器
1.效果图
2.安装插件
npm install quill-image-resize-module quill-image-drop-module --save
3.在编辑器页面导入相关组件
import { ImageDrop } from 'quill-image-drop-module'
import ImageResize from 'quill-image-resize-module'
Quill.register('modules/imageDrop', ImageDrop)
Quill.register('modules/imageResize', ImageResize)
在editorOption添加如下代码
history: {
delay: 1000,
maxStack: 50,
userOnly: false
},
imageDrop: true,
imageResize: {
displayStyles: {
backgroundColor: 'black',
border: 'none',
color: 'white'
},
modules: [ 'Resize', 'DisplaySize', 'Toolbar' ]
}
4.配置相关设置
vue-cli2.0
去build文件夹下的webpack.dev.conf.js文件里
在plugins[]里面加上
new webpack.ProvidePlugin({
'window.Quill': 'quill/dist/quill.js',
'Quill': 'quill/dist/quill.js'
}),
vue-cli3.0
自己创建一个vue.config.js文件(和src同级别的)
const webpack = require('webpack')
module.exports = {
chainWebpack: config => {
config.plugin('provide').use(webpack.ProvidePlugin, [{
'window.Quill': 'quill/dist/quill.js',
'Quill': 'quill/dist/quill.js'
}]);
}
}
五·完整代码
<template>
<div class="main">
<!-- 图片上传组件辅助-->
<el-upload
class="editor-uploader"
:action="uploadUrl"
:show-file-list="false"
:headers="headers"
:on-success="uploadSuccess"
:before-upload="beforeUpload"
>
</el-upload>
<quill-editor
v-model="ruleForm.rule"
ref="myQuillEditor"
style="width: 100%; height: 500px"
:options="editorOption"
>
<!-- 自定义toolar -->
<div id="toolbar" slot="toolbar">
<button class="ql-bold" title="加粗">Bold</button>
<button class="ql-italic" title="斜体">Italic</button>
<button class="ql-underline" title="下划线">underline</button>
<button class="ql-strike" title="删除线">strike</button>
<button class="ql-blockquote" title="引用"></button>
<button class="ql-code-block" title="代码"></button>
<button class="ql-header" value="1" title="标题1"></button>
<button class="ql-header" value="2" title="标题2"></button>
<button
class="ql-list"
value="ordered"
title="有序列表"
></button>
<button
class="ql-list"
value="bullet"
title="无序列表"
></button>
<select
class="ql-header"
title="段落格式"
style="line-height: 24px; text-align: center"
>
<option selected>段落</option>
<option value="1">标题1</option>
<option value="2">标题2</option>
<option value="3">标题3</option>
<option value="4">标题4</option>
<option value="5">标题5</option>
<option value="6">标题6</option>
</select>
<select
class="ql-size"
title="字体大小"
style="line-height: 24px; text-align: center"
>
<option value="10px">10px</option>
<option value="12px">12px</option>
<option value="14px">14px</option>
<option value="16px" selected>16px</option>
<option value="18px">18px</option>
<option value="20px">20px</option>
</select>
<select
class="ql-font"
title="字体"
style="line-height: 24px; text-align: center"
>
<option value="SimSun">宋体</option>
<option value="SimHei">黑体</option>
<option value="Microsoft-YaHei">微软雅黑</option>
<option value="KaiTi">楷体</option>
<option value="FangSong">仿宋</option>
<option value="Arial">Arial</option>
</select>
<select
class="ql-color"
value="color"
title="字体颜色"
style="line-height: 24px; text-align: center"
></select>
<select
class="ql-background"
value="background"
title="背景颜色"
style="line-height: 24px; text-align: center"
></select>
<select
class="ql-align"
value="align"
title="对齐"
style="line-height: 24px; text-align: center"
></select>
<button class="ql-image" title="图片"></button>
<button class="ql-clean" title="还原"></button>
</div>
</quill-editor>
</div>
</template>
<script>
// 富文本编辑器
import { Quill, quillEditor } from "vue-quill-editor";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
//引入font.css
import "../../../assets/css/font.css";
// 富文本图片编辑
import { ImageDrop } from "quill-image-drop-module";
import ImageResize from "quill-image-resize-module";
Quill.register("modules/imageDrop", ImageDrop);
Quill.register("modules/imageResize", ImageResize);
// 自定义字体大小
let Size = Quill.import("attributors/style/size");
Size.whitelist = ["10px", "12px", "14px", "16px", "18px", "20px"];
Quill.register(Size, true);
// 自定义字体类型
var fonts = [
"SimSun",
"SimHei",
"Microsoft-YaHei",
"KaiTi",
"FangSong",
"Arial",
"Times-New-Roman",
"sans-serif",
"宋体",
"黑体",
];
var Font = Quill.import("formats/font");
Font.whitelist = fonts;
Quill.register(Font, true);
export default {
// 组件
components: {
quillEditor,
},
name: "Index",
data() {
return {
editorOption: {
placeholder: "请输入规则内容···",
theme: "snow", //主题 snow/bubble
modules: {
history: {
delay: 1000,
maxStack: 50,
userOnly: false,
},
imageDrop: true,
imageResize: {
displayStyles: {
backgroundColor: "black",
border: "none",
color: "white",
},
modules: ["Resize", "DisplaySize", "Toolbar"],
},
toolbar: {
container: "#toolbar",
handlers: {
image: function (value) {
if (value) {
// 调用element的图片上传组件
document.querySelector(".editor-uploader input").click();
} else {
this.quill.format("image", false);
}
},
},
},
},
},
uploadUrl: "https://XXXX", // 服务器上传地址
// 上传图片参数
headers: {
Authorization: "Bearer " + localStorage.getItem("token"), //从cookie里获取token,并赋值 Authorization ,而不是token
},
};
},
created() {
},
methods: {
// 富文本编辑器值发生变化
onEditorChange(editor) {
this.content = editor.html;
console.log(editor);
},
// 富文本图片上传处理
beforeUpload(file) {},
uploadSuccess(res) {
// 获取富文本组件实例
let quill = this.$refs.myQuillEditor.quill;
// 如果上传成功
if (res) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片,res为服务器返回的图片链接地址
quill.insertEmbed(length, "image", res.data);
// 调整光标到最后
quill.setSelection(length + 1);
} else {
// 提示信息,需引入Message
this.$message.error("图片插入失败!");
}
},
},
};
</script>
<style lang="scss">
// 富文本编辑器图片上传隐藏
.editor-uploader {
display: none;
}
</style>
六·感谢以下大佬
参考1
https://blog.csdn.net/TauCrus/article/details/88801941
参考2
https://www.jianshu.com/p/42bc2db19fab
参考3
https://blog.csdn.net/weixin_43953710/article/details/99301369