目录版本 环境搭建新建vue 增加ArcGIS JavaScript 包引用 拷贝资源信息页面测试版本 Vue 2 ArcGIS JavaScript 4.22 注意 ArcGIS JavaScrip
顺晟科技
2022-09-23 10:54:42
235
前言:vue中很多项目都需要用到富文本编辑器,在使用了ueditor和tinymce后,发现并不理想。所以果断使用vue-quill-editor来实现。
- wangEditor(国产,基于javascript和css开发的web富文本编辑器,开源免费)优势:轻量简介,最重要的是开源且中文文档齐全。缺点:更新不及时。没有强大的开发团队支撑。
- UEditor(百度)优势:插件多,基本曼度各种需求,由百度web前端研发部开发。缺点:插件提交较大,网页加载速度相对就慢了些。使用复杂。属于前后端不分离插件。在使用时需要配置后端的一些东西,使用不便。
- Kindeditor () 优势:文档齐全,为中文,阅读方便。缺点:图片上传存在问题,上传历史过多,会全部加载,导致浏览器卡顿。
- 补充:Tinymce也是一款不错的富文本编辑器,种植,各有优势和劣势,关键是选择一款最适合的就好。因为笔者在开发vue,所以直接使用vue-quill-editor较为方便些。具体看情况使用。
npm install vue-quill-editor -s
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/bubble syntax: 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>实现以上配置后就可以看到效果如图:
因为图片这块,大多情况下,我们都不需要base64格式的,所以我们需要将图片通过OSS换取网络路径然后发送给后端和回显。
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-upload class="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-editor class="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: "https://testihospitalapi.ebaiyihui.com/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>还有一种方式是不借助element-ui来实现图片上传,这一过程无非就是图片上传OSS换取网络路径,这一块,咱们其实可以自定义图片上传组件。这里就不做阐述了,笔者的另一篇图片上传的组件文章(https://www.cnblogs.com/bgwhite/p/10123065.html),大家在这里就可以使用起来。
09
2022-11
09
2022-11
09
2022-11
19
2022-10
19
2022-10
19
2022-10