vue-quill-editor富文本编辑器 中文翻译组件,编辑与展示
vue项目中用到了富文本编辑器,网上找了一些,觉得vue-quill-editor最好用,
ui简洁,功能也好配,够用了,文档不好读,有些小细节需要自己注意,我懒得分析,就封装成了组件
大家用的时候直接cope组件,但是不要cope文章呀~~~
需要注意的是编辑器保存的格式,我们在用div展示的时候,有些格式无效,所以我也同样封装了供页面展示的组件
首先安装包
npm 安装 vue-quill-editor
这是编辑器效果图:

这是编辑器的组件代码:
代码比较多,我折叠起来了
<template>
<div class="editor_wrap">
<!-- 图片上传组件辅助-->
<el-upload
class="avatar-uploader"
:action="serverUrl"
name="image"
:headers="header"
multiple
:show-file-list="false"
:on-success="uploadSuccess"
:on-error="uploadError"
:before-upload="beforeUpload"
></el-upload>
<quill-editor
v-loading="quillUpdateImg"
class="editor"
v-model="content"
ref="myQuillEditor"
:options="editorOption"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@change="onEditorChange($event)"
></quill-editor>
</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";
// 工具栏配置
const toolbarOptions = [
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
["blockquote", "code-block"], // 引用 代码块
// [{ header: 1 }, { header: 2 }], // 1、2 级标题
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
[{ script: "sub" }, { script: "super" }], // 上标/下标
[{ indent: "-1" }, { indent: "+1" }], // 缩进 2
[{ color: [
'#ffffff', '#ffd7d5', '#ffdaa9', '#fffed5', '#d4fa00', '#73fcd6', '#a5c8ff', '#ffacd5', '#ff7faa',
'#d6d6d6', '#ffacaa', '#ffb995', '#fffb00', '#73fa79', '#00fcff', '#78acfe', '#d84fa9', '#ff4f79',
'#b2b2b2', '#d7aba9', '#ff6827', '#ffda51', '#00d100', '#00d5ff', '#0080ff', '#ac39ff', '#ff2941',
'#888888', '#7a4442', '#ff4c00', '#ffa900', '#3da742', '#3daad6', '#0052ff', '#7a4fd6', '#d92142',
'#000000', '#7b0c00', '#ff0000', '#d6a841', '#407600', '#007aaa', '#021eaa', '#797baa', '#ab1942'
] }, { background: [
'#ffffff', '#ffd7d5', '#ffdaa9', '#fffed5', '#d4fa00', '#73fcd6', '#a5c8ff', '#ffacd5', '#ff7faa',
'#d6d6d6', '#ffacaa', '#ffb995', '#fffb00', '#73fa79', '#00fcff', '#78acfe', '#d84fa9', '#ff4f79',
'#b2b2b2', '#d7aba9', '#ff6827', '#ffda51', '#00d100', '#00d5ff', '#0080ff', '#ac39ff', '#ff2941',
'#888888', '#7a4442', '#ff4c00', '#ffa900', '#3da742', '#3daad6', '#0052ff', '#7a4fd6', '#d92142',
'#000000', '#7b0c00', '#ff0000', '#d6a841', '#407600', '#007aaa', '#021eaa', '#797baa', '#ab1942'
] }], // 字体颜色、字体背景颜色
[{ size: ["small", false, "large", "huge"] }], // 字体大小 2
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ font: [] }], // 字体种类 2
[{'direction': 'rtl'}], // 文本方向 2
[{ align: [] }], // 对齐方式 2
["clean"], // 清除文本格式
["link", "image", "video"] // 链接、图片、视频
];
export default {
props: {
/*编辑器的内容*/
value: null,
/*图片大小*/
maxSize: {
type: Number,
default: 4000 //kb
}
}, components: {
quillEditor
},
watch: {
value(val) {
this.content = this.value
}
}, data() {
return {
content: this.value,
quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
editorOption: {
theme: "snow", // or 'bubble'
placeholder: "您想说点什么?",
modules: {
toolbar: {
container: toolbarOptions,
handlers: {
image: function(value) {
if (value) {
// 触发input框选择图片文件
document.querySelector(".avatar-uploader input").click();
} else {
this.quill.format("image", false);
}
},
// link: function(value) {
// if (value) {
// var href = prompt('请输入url');
// this.quill.format("link", href);
// } else {
// this.quill.format("link", false);
// }
// },
}
}
}
},
serverUrl: process.env.VUE_APP_API_URL + "config/upload", // 这里写你要上传的图片服务器地址
header: {
token: localStorage.getItem("token")
}
};
}, methods: {
onEditorBlur() {
//失去焦点事件
},
onEditorFocus() {
//获得焦点事件
},
onEditorChange({ editor, html, text }) {
this.content = html;
//内容改变事件
this.$emit("textareaData", this.content);
}, // 富文本图片上传前
beforeUpload() {
// 显示loading动画
this.quillUpdateImg = true;
}, uploadSuccess(res, file) {
// res为图片服务器返回的数据
// 获取富文本组件实例
let quill = this.$refs.myQuillEditor.quill;
// 如果上传成功
if (res.error == 0) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片 res.url为服务器返回的图片地址
quill.insertEmbed(length, "image", res.info.img_url);
// 调整光标到最后
quill.setSelection(length + 1);
} else {
this.$message.error("图片插入失败");
}
// loading动画消失
this.quillUpdateImg = false;
},
// 富文本图片上传失败
uploadError() {
// loading动画消失
this.quillUpdateImg = false;
this.$message.error("图片插入失败");
}
}
};
</script> <style scoped>
.editor_wrap /deep/ .avatar-uploader {
display: none;
}
.editor_wrap /deep/ .editor {
line-height: normal !important;
height: 270px;
margin-bottom: 60px;
}
.editor_wrap /deep/ .editor .ql-bubble .ql-editor a {
color: #136ec2;
}
.editor_wrap /deep/ .editor img {
max-width: 720px;
margin:10px;
}
.editor_wrap /deep/ .ql-snow .ql-color-picker .ql-picker-options {
padding: 3px 5px;
width: 192px;
}
.editor_wrap /deep/ .ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:";
}
.editor_wrap /deep/ .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
} .editor_wrap /deep/ .ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:";
} .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-label::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
} .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6";
} .editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-label::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "衬线字体";
}
.editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "等宽字体";
}
</style>
这是供页面展示的效果图:

这是供页面展示的组件代码:
代码比较多,同样我折叠起来了
<template>
<div class="editor_wrap">
<quill-editor
class="editor"
v-model="content"
ref="myQuillEditor"
:options="editorOption"
@focus="onEditorFocus($event)"
></quill-editor>
</div>
</template>
<script>
// 工具栏配置
const toolbarOptions = []; 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 {
props: {
/*编辑器的内容*/
value: null
},
components: {
quillEditor
},
watch: {
value(val) {
this.content = this.value;
}
},
computed: {
editor() {
return this.$refs.myQuillEditor.quill;
}
},
data() {
return {
content: this.value,
editorOption: {
theme: "bubble", // or 'bubble'
placeholder: "您想说点什么?",
modules: {
toolbar: {
container: toolbarOptions,
handlers: {}
}
}
}
};
},
methods: {
onEditorFocus(editor) {
// 富文本获得焦点时的事件
editor.enable(false); // 在获取焦点的时候禁用
}
}
};
</script> <style scoped>
.editor_wrap /deep/ .editor img {
max-width: 720px;
margin:10px;
}
.editor_wrap /deep/ .editor .ql-bubble .ql-editor a {
color: #136ec2;
}
</style>
值得注意的是页面展示的时候,会有一个鼠标光标出现,目前我没有处理,欢迎大神们留言指导
vue-quill-editor富文本编辑器 中文翻译组件,编辑与展示的更多相关文章
- Vue基于vue-quill-editor富文本编辑器使用心得
vue-quill-editor的guthub地址,现在市面上有很多的富文本编辑器,我个人还是非常推荐Vue自己家的vue-quill-deitor,虽然说只支持IE10+,但这种问题,帅给别人吧! ...
- Vue集成tinymce富文本编辑器并实现本地化指南(2019.11.21最新)
tinymce是一款综合口碑特别好.功能异常强大的富文本编辑器,在某些网站,甚至享有"宇宙最强富文本编辑器"的称号.那么,在Vue项目中如何集成呢?这并不困难,只需要参照官方教程 ...
- vue集成百度富文本编辑器
1.前期工作,访问百度富文本官网下载相应的百度富文本文件,根据后端用的技术下载相应的版本,建议下载最新版UTF-8版 (有图有真相,看图) https://ueditor.baidu.com/webs ...
- 关于百度Editor富文本编辑器 自定义上传位置
因为要在网站上编辑富文本数据,所以直接采用百度的富文本编辑器,但是这个编辑器有个缺点,默认情况下,文件只能上传到网站的根目录,不能自定义路径. 而且json配置文件只能和controller.jsp在 ...
- tinymce-vue富文本编辑器(翻译)
官方Tinymce Vue组件 翻译来自:https://github.com/tinymce/tinymce-vue 官方文档:https://www.tiny.cloud/docs/general ...
- vue 集成百度富文本编辑器
<template> <div> <textarea style="display:none" id="editor_content&quo ...
- BRAFT EDITOR富文本编辑器
https://braft.margox.cn/demos/basic 官方文档 import React from 'react' import Uploading from '../Upl ...
- vue 富文本编辑器 项目实战用法
1.挑个富文本编辑器 首先针对自己项目的类型,确定自己要用啥编辑器. 1.1 wangeditor 如果一般类似博客这种项目不需要花里胡哨的,功能也不要求贼多的,推荐一下wangeditor(点击跳转 ...
- 现代富文本编辑器Quill的模块化机制
DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...
随机推荐
- 201871010134-周英杰《面向对象程序设计(java)》第十周学习总结
import java.io.FileInputStream; import java.io.FileNotFoundException; public class ExceptionText1 { ...
- 没有重写接口方法,IDEA没有报错。
今天在IDEA写拦截器的时候遇到点困惑,继承了HandlerInterceptor没有报错,我一直认为他会提醒,要重写方法.如下图 通过查资料,嗯,终于找到原因来,先来上HandlerIntercep ...
- sqler 2.2 发布了,支持定时任务以及触发器
sqler 在10前发布了,2.2 添加了定时任务以及触发器(webhook),都是比较方便的功能, 同时我也修改了dockerfile, 做了构建,添加了功能支持,同时push 到了dockerhu ...
- TensorFlow基础篇
Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算.TensorFlow的运行机制属于“定义”和“运行”相分离.模型的构建只是相当于定义了一个图结构(代表一个计算任务),图中有 ...
- MySQL实战45讲学习笔记:第二十三讲
一.本节概要 今天这篇文章,我会继续和你介绍在业务高峰期临时提升性能的方法.从文章标题“MySQL 是怎么保证数据不丢的?”,你就可以看出来,今天我和你介绍的方法,跟数据的可靠性有关. 在专栏前面文章 ...
- c++性能测试工具:计算时间复杂度
有时候除了测量算法的具体性能指数,我们也会希望测试出算法的时间复杂度,以便我们对待测试的算法的性能有一个更加直观的了解. 测量时间复杂度 google benchmark已经为我们提供了类似的功能,而 ...
- 推荐一款语音直播连麦App YAMI
推荐一款语音直播连麦App YAMI 1 介绍 功能描述:[语音直播]:海量超有才主播,游戏送礼抢红包,嗨玩不停:[多人聊天室]:连麦交友处CP,主持人带你玩游戏,边聊边玩:[语音交友]:海量声优专属 ...
- Adams宏导出
var set var=ip integer_value=1 var set var=macro_name str="" for variable_name=the_macro o ...
- 使用thanos管理Prometheus持久化数据
关于thanos的介绍可以参考这篇官方博客的翻译文档,本文不作部署操作介绍.下图是thanos的官方架构图,主要有5个组件: Query:可以近似看作是Prometheus的实现,用于采集其他组件的数 ...
- 异步IO与回调
最好了解 Java NIO 中 Buffer.Channel 和 Selector 的基本操作,主要是一些接口操作,比较简单. 本文将介绍非阻塞 IO 和异步 IO,也就是大家耳熟能详的 NIO 和 ...