700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > vue富文本编辑器 Vue-Quill-Editor

vue富文本编辑器 Vue-Quill-Editor

时间:2019-02-14 03:52:37

相关推荐

vue富文本编辑器 Vue-Quill-Editor

主流富文本编辑器对比

前言:vue中很多项目都需要用到富文本编辑器,在使用了ueditor和tinymce后,发现并不理想。所以果断使用vue-quill-editor来实现。

wangEditor(国产,基于javascript和css开发的web富文本编辑器,开源免费)优势:轻量简介,最重要的是开源且中文文档齐全。缺点:更新不及时。没有强大的开发团队支撑。

UEditor(百度)优势:插件多,基本曼度各种需求,由百度web前端研发部开发。缺点:插件提交较大,网页加载速度相对就慢了些。使用复杂。属于前后端不分离插件。在使用时需要配置后端的一些东西,使用不便。

Kindeditor () 优势:文档齐全,为中文,阅读方便。缺点:图片上传存在问题,上传历史过多,会全部加载,导致浏览器卡顿。

补充:Tinymce也是一款不错的富文本编辑器,种植,各有优势和劣势,关键是选择一款最适合的就好。因为笔者在开发vue,所以直接使用vue-quill-editor较为方便些。具体看情况使用。

vue-quill-editor基本配置

npm install vue-quill-editor -s

main.js中引入

import VueQuillEditor from 'vue-quill-editor'import 'quill/dist/quill.core.css'import 'quill/dist/quill.snow.css'import 'quill/dist/quill.bubble.css'Vue.use(VueQuillEditor);

使用

需要注意的是toolbar的配置

1. 只需要填写功能名的

加粗 - bold;斜体 - italic下划线 - underline删除线 - strike引用- blockquote代码块 - code-block公式 - formula图片 - image视频 - video清除字体样式- clean这一类的引用 直接['name','name']这种格式就好了

2. 需要有默认值的

标题 - header [{ 'header': 1 }, { 'header': 2 }] 值字体大小列表 - list[{ 'list': 'ordered'}, { 'list': 'bullet' }], 值ordered,bullet上标/下标 - script[{ 'script': 'sub'}, { 'script': 'super' }], 值sub,super缩进 - indent[{ 'indent': '-1'}, { 'indent': '+1' }], 值-1,+1等文本方向 - direction[{'direction':'rtl'}]

结构

<template><quill-editor class="editor"ref="myTextEditor"v-model="content":options="editorOption"@blur="onEditorBlur($event)"@focus="onEditorFocus($event)"@ready="onEditorReady($event)"@change="onEditorChange($event)"></quill-editor></template><script>export default {data () {return {content: null,editorOption: {modules: {toolbar: [["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" }], // 缩进// [{'direction': 'rtl'}],// 文本方向[{ size: ["small", false, "large", "huge"] }], // 字体大小[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色[{ font: [] }], // 字体种类[{ align: [] }], // 对齐方式["clean"], // 清除文本格式["link", "image", "video"] // 链接、图片、视频], //工具菜单栏配置},placeholder: '请在这里添加产品描述', //提示readyOnly: false, //是否只读theme: 'snow', //主题 snow/bubblesyntax: true, //语法检测}}},methods: {// 失去焦点onEditorBlur(editor) {},// 获得焦点onEditorFocus(editor) {},// 开始onEditorReady(editor) {},// 值发生变化onEditorChange(editor) {this.content = editor.html;console.log(editor);},},computed: {editor() {return this.$refs.myTextEditor.quillEditor;}},mounted() {// console.log('this is my editor',this.editor);} }</script>

汉化

汉化只需要更改toolbar工具栏中的样式即可实现

<style>.editor {line-height: normal !important;height: 800px;}.ql-snow .ql-tooltip[data-mode=link]::before {content: "请输入链接地址:";}.ql-snow .ql-tooltip.ql-editing a.ql-action::after {border-right: 0px;content: '保存';padding-right: 0px;}.ql-snow .ql-tooltip[data-mode=video]::before {content: "请输入视频地址:";}.ql-snow .ql-picker.ql-size .ql-picker-label::before,.ql-snow .ql-picker.ql-size .ql-picker-item::before {content: '14px';}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {content: '10px';}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {content: '18px';}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {content: '32px';}.ql-snow .ql-picker.ql-header .ql-picker-label::before,.ql-snow .ql-picker.ql-header .ql-picker-item::before {content: '文本';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {content: '标题1';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {content: '标题2';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {content: '标题3';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {content: '标题4';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {content: '标题5';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {content: '标题6';}.ql-snow .ql-picker.ql-font .ql-picker-label::before,.ql-snow .ql-picker.ql-font .ql-picker-item::before {content: '标准字体';}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {content: '衬线字体';}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {content: '等宽字体';}</style>

以上就是vue-quill-editor的基本配置了。

图片上传的配置

因为图片这块,大多情况下,我们都不需要base64格式的,所以我们需要将图片通过OSS换取网络路径然后发送给后端和回显

更换quill-editor的点击事件为自定义事件

这里借助element-ui的图片功能,因为其功能齐全,图片上传前,上传后,都有交互效果的处理,所以可以选择性使用

editorOption: {modules: {toolbar: {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);// }// },}}}},

而后在自定义的元素上写入点击事件,然后将该元素隐藏掉。点击quill-editor的图片上传时,实际点击了自定义的图片上传,而后在返回网络路径后将图片插入富文本编辑器即可。

插入返回的网络图片路径(这里借助的是element-ui)

uploadSuccess(res, file) {// res为图片服务器返回的数据// 获取富文本组件实例let quill = this.$refs.myQuillEditor.quill;// 如果上传成功if (res.code == 200) {// 获取光标所在位置let length = quill.getSelection().index;// 插入图片 res.url为服务器返回的图片地址quill.insertEmbed(length, "image", res.url);// 调整光标到最后quill.setSelection(length + 1);} else {this.$message.error("图片插入失败");}// loading动画消失this.quillUpdateImg = false;},

以上就是主要思路及代码,如果还是不懂就看下面vue组件的源码(也可直接使用,前提是下载了element-ui)

组件封装源码及引用

<template><div><!-- 图片上传组件辅助--><el-uploadclass="avatar-uploader":action="serverUrl"name="file":headers="header":show-file-list="false"list-type="picture":multiple="false":on-success="uploadSuccess":on-error="uploadError":before-upload="beforeUpload"></el-upload><quill-editorclass="editor"v-model="content"ref="myQuillEditor":options="editorOption"@blur="onEditorBlur($event)" @focus="onEditorFocus($event)"@change="onEditorChange($event)"></quill-editor></div></template><script>// 工具栏配置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" }], // 缩进// [{'direction': 'rtl'}],// 文本方向[{ size: ["small", false, "large", "huge"] }], // 字体大小[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色[{ font: [] }], // 字体种类[{ align: [] }], // 对齐方式["clean"], // 清除文本格式["link", "image", "video"] // 链接、图片、视频];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: {type: String},/*图片大小*/maxSize: {type: Number,default: 4000 //kb}},components: {quillEditor},data() {return {content: this.value,quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示editorOption: {theme: "snow", // or 'bubble'placeholder: "您想说点什么?",modules: {toolbar: {container: toolbarOptions,// container: "#toolbar",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: "/oss/api/file/store/v1/saveFile", // 这里写你要上传的图片服务器地址header: {// token: sessionStorage.token} // 有的图片服务器要求请求头需要有token};},methods: {onEditorBlur() {//失去焦点事件},onEditorFocus() {//获得焦点事件},onEditorChange() {//内容改变事件this.$emit("input", this.content);},// 富文本图片上传前beforeUpload() {// 显示loading动画this.quillUpdateImg = true;},uploadSuccess(res, file) {// res为图片服务器返回的数据// 获取富文本组件实例let quill = this.$refs.myQuillEditor.quill;// 如果上传成功if (res.code == 200) {// 获取光标所在位置let length = quill.getSelection().index;// 插入图片 res.url为服务器返回的图片地址quill.insertEmbed(length, "image", res.result.url);// 调整光标到最后quill.setSelection(length + 1);} else {this.$message.error("图片插入失败");}// loading动画消失this.quillUpdateImg = false;},// 富文本图片上传失败uploadError() {// loading动画消失this.quillUpdateImg = false;this.$message.error("图片插入失败");}}};</script><style>.editor {line-height: normal !important;height: 800px;}.ql-snow .ql-tooltip[data-mode=link]::before {content: "请输入链接地址:";}.ql-snow .ql-tooltip.ql-editing a.ql-action::after {border-right: 0px;content: '保存';padding-right: 0px;}.ql-snow .ql-tooltip[data-mode=video]::before {content: "请输入视频地址:";}.ql-snow .ql-picker.ql-size .ql-picker-label::before,.ql-snow .ql-picker.ql-size .ql-picker-item::before {content: '14px';}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {content: '10px';}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {content: '18px';}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {content: '32px';}.ql-snow .ql-picker.ql-header .ql-picker-label::before,.ql-snow .ql-picker.ql-header .ql-picker-item::before {content: '文本';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {content: '标题1';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {content: '标题2';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {content: '标题3';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {content: '标题4';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {content: '标题5';}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {content: '标题6';}.ql-snow .ql-picker.ql-font .ql-picker-label::before,.ql-snow .ql-picker.ql-font .ql-picker-item::before {content: '标准字体';}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {content: '衬线字体';}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {content: '等宽字体';}</style>引入:<template><Editor v-model="article.content"/></template><script>import Editor from './quillEditor'export default {components: {Editor},data() {return {article: {content: '',}}}}</script><style></style>

VUE组件封装

<template><quill-editorclass="editor"ref="myTextEditor"v-model="content":options="editorOption"@change="onEditorChange($event)"></quill-editor></template><script>const toolbar = [["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" }], // 缩进// [{'direction': 'rtl'}],// 文本方向[{ size: ["small", false, "large", "huge"] }], // 字体大小[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色[{ font: [] }], // 字体种类[{ align: [] }], // 对齐方式["clean"], // 清除文本格式["link", "image", "video"] // 链接、图片、视频]; //工具菜单栏配置export default {data() {return {content: null, //内容editorOption: {modules: {toolbar},placeholder: "", //提示readyOnly: false, //是否只读theme: "snow", //主题 snow/bubblesyntax: true //语法检测}};},methods: {// 值发生变化onEditorChange(editor) {this.content = editor.html;this.$emit("content", editor.html);}}};</script><style>.editor {line-height: normal !important;height: 800px;margin-bottom: 30px;}.ql-snow .ql-tooltip[data-mode="link"]::before {content: "请输入链接地址:";}.ql-snow .ql-tooltip.ql-editing a.ql-action::after {border-right: 0px;content: "保存";padding-right: 0px;}.ql-snow .ql-tooltip[data-mode="video"]::before {content: "请输入视频地址:";}.ql-snow .ql-picker.ql-size .ql-picker-label::before,.ql-snow .ql-picker.ql-size .ql-picker-item::before {content: "14px";}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {content: "10px";}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {content: "18px";}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {content: "32px";}.ql-snow .ql-picker.ql-header .ql-picker-label::before,.ql-snow .ql-picker.ql-header .ql-picker-item::before {content: "文本";}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {content: "标题1";}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {content: "标题2";}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {content: "标题3";}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {content: "标题4";}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {content: "标题5";}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {content: "标题6";}.ql-snow .ql-picker.ql-font .ql-picker-label::before,.ql-snow .ql-picker.ql-font .ql-picker-item::before {content: "标准字体";}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {content: "衬线字体";}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {content: "等宽字体";}</style>

还有一种方式是不借助element-ui来实现图片上传,这一过程无非就是图片上传OSS换取网络路径,这一块,咱们其实可以自定义图片上传组件。这里就不做阐述了

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。