问题描述我们在开发过程中经常会遇到使用富文本编辑器进行操作当前插件市场上关于富文本的编辑器挺多的我们就不一一个介绍了现在我们主要讲解一些vue-quill-editor富文本编辑器的使用操作和注意事项。效果图具体操作使用1. 安装npm install vue-quill-editor-S2. 引入到项目中有两种挂载方式 全局挂载 和 在组件中挂载根据自己的项目需求选择一般用到富文本编辑都是在某一个项目中我们这里为了方便大家选择两种引用方案都写下来以便大家参考1页面中引用import{quillEditor}fromvue-quill-editorimportquill/dist/quill.core.cssimportquill/dist/quill.snow.cssimportquill/dist/quill.bubble.cssexportdefault{components:{quillEditor}}2全局中引用importVuefromvueimportVueQuillEditorfromvue-quill-editor// 引入样式importquill/dist/quill.core.cssimportquill/dist/quill.snow.cssimportquill/dist/quill.bubble.cssVue.use(VueQuillEditor,/* { 默认全局 } */)3. 页面上面具体实现templatequill-editorclassql-editorv-modelcontentrefmyQuillEditor:optionseditorOptionbluronEditorBlur($event)focusonEditorFocus($event)changeonEditorChange($event)/quill-editor/templatescriptexportdefault{data(){return{content:p这是 vue-quill-editor 的内容/p,//双向数据绑定数据// 富文本编辑器配置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:[12px,false,16px,18px,20px,30px]}],// 字体大小[{header:[1,2,3,4,5,6,false]}],// 标题[{color:[]},{background:[]}],// 字体颜色、字体背景颜色[{font:[false,SimSun,SimHei,Microsoft-YaHei,KaiTi,FangSong,Arial]}],// 字体种类[{align:[]}],// 对齐方式[clean],// 清除文本格式[link,image,video]// 链接、图片、视频},placeholder:请输入正文}}},methods:{// 失去焦点事件onEditorBlur(quill){console.log(editor blur!,quill)},// 获得焦点事件onEditorFocus(quill){console.log(editor focus!,quill)},// 准备富文本编辑器onEditorReady(quill){console.log(editor ready!,quill)},// 内容改变事件onEditorChange({quill,html,text}){console.log(editor change!,quill,html,text)this.contenthtml}}}/script到这里一个默认的富文本编辑器已经导入使用了如下图所视4.为了更好配合使用样式上面进行优化使用中文标识方便查看1重新自定义字体类型importQuillfromquill// 引入编辑器// 自定义字体大小constSizeQuill.import(attributors/style/size)Size.whitelist[10px,12px,16px,18px,20px,30px,32px]Quill.register(Size,true)// 自定义字体类型varfonts[SimSun,SimHei,Microsoft-YaHei,KaiTi,FangSong,Arial,sans-serif]varFontQuill.import(formats/font)Font.whitelistfonts Quill.register(Font,true)2自定义对应样式// 给文本内容加高度滚动条 .quill-editor /deep/ .ql-container { min-height: 220px; } .ql-container { min-height: 230px; } /deep/ { .ql-snow .ql-tooltip [data-modelink]::before { content: 请输入链接地址:; left: 0; } .ql-snow .ql-tooltip.ql-editing { left: 0 !important; } .ql-snow .ql-tooltip { left: 0 !important; } .ql-snow .ql-editor { max-height: 300px; } .ql-snow .ql-tooltip.ql-editing a.ql-action::after { border-right: 0px; content: 保存; padding-right: 0px; } .ql-snow .ql-tooltip[data-modevideo]::before { content: 请输入视频地址:; } .ql-snow .ql-picker.ql-size .ql-picker-label::before, .ql-snow .ql-picker.ql-size .ql-picker-item::before { content: 14px !important; font-size: 14px; } .ql-snow .ql-picker.ql-size .ql-picker-label[data-value10px]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value10px]::before { content: 10px !important; font-size: 10px; } .ql-snow .ql-picker.ql-size .ql-picker-label[data-value12px]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value12px]::before { content: 12px !important; font-size: 12px; } .ql-snow .ql-picker.ql-size .ql-picker-label[data-value16px]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value16px]::before { content: 16px !important; font-size: 16px; } .ql-snow .ql-picker.ql-size .ql-picker-label[data-value18px]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value18px]::before { content: 18px !important; font-size: 18px; } .ql-snow .ql-picker.ql-size .ql-picker-label[data-value20px]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value20px]::before { content: 20px !important; font-size: 20px; } .ql-snow .ql-picker.ql-size .ql-picker-label[data-value30px]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value30px]::before { content: 30px !important; font-size: 30px; } .ql-snow .ql-picker.ql-size .ql-picker-label[data-value32px]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value32px]::before { content: 32px !important; font-size: 32px; } .ql-snow .ql-picker.ql-header .ql-picker-label::before, .ql-snow .ql-picker.ql-header .ql-picker-item::before { content: 文本 !important; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value1]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value1]::before { content: 标题1 !important; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value2]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value2]::before { content: 标题2 !important; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value3]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value3]::before { content: 标题3 !important; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value4]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value4]::before { content: 标题4 !important; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value5]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value5]::before { content: 标题5 !important; } .ql-snow .ql-picker.ql-header .ql-picker-label[data-value6]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value6]::before { content: 标题6 !important; } .ql-snow .ql-picker.ql-font .ql-picker-label::before, .ql-snow .ql-picker.ql-font .ql-picker-item::before { content: 标准字体 !important; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueserif]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueserif]::before { content: 衬线字体 !important; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valuemonospace]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valuemonospace]::before { content: 等宽字体 !important; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueSimSun]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueSimSun]::before { content: 宋体 !important; font-family: SimSun; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueSimHei]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueSimHei]::before { content: 黑体 !important; font-family: SimHei; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueMicrosoft-YaHei]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueMicrosoft-YaHei]::before { content: 微软雅黑 !important; font-family: Microsoft YaHei; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueKaiTi]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueKaiTi]::before { content: 楷体 !important; font-family: KaiTi; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueFangSong]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueFangSong]::before { content: 仿宋 !important; font-family: FangSong; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueArial]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueArial]::before { content: Arial !important; font-family: Arial; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueTimes-New-Roman]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueTimes-New-Roman]::before { content: Times New Roman !important; font-family: Times New Roman; } .ql-snow .ql-picker.ql-font .ql-picker-label[data-valuesans-serif]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valuesans-serif]::before { content: sans-serif !important; 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; } .ql-snow.ql-toolbar .ql-formats .ql-revoke { background-image: url(../../../../assets/images/icons8-rotate-left-18.png); width: 20px; height: 20px; filter: grayscale(100%); opacity: 1; } .ql-snow.ql-toolbar .ql-formats .ql-revoke:hover { background-image: url(../../../../assets/images/icons8-rotate-left-18.png); width: 20px; height: 20px; filter: none; opacity: 0.9; } img { filter: grayscale(100%); opacity: 1; } img:hover { filter: none; opacity: 0.9; } /*加上height和滚动属性就可以滚动条样式是系统默认样式可能不同*/ .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options { border-color: #ccc; height: 125px; overflow: auto; } }3注意点富文本里面的下拉框默认是不滚动的想要滚动效果加上下面的css/*加上height和滚动属性就可以滚动条样式是系统默认样式可能不同*/.ql-toolbar.ql-snow.ql-picker.ql-expanded.ql-picker-options{border-color:#ccc;height:125px;overflow:auto;}5.上传图片到七牛云vue-quill-editor 默认的是以 base64 保存图片会直接把图片 base64 和内容文本一起以字符串的形式提交到后端。这样小图片还行如果要上传大图片会提示上传失败优秀的前端打字员显然不会这样做。思路可以先将图片上传至服务器再将图片链接插入到富文本中显示图片上传可以自定义一个组件或者使用 element-ui 的上传图片的组件我在项目中使用的是自定义的组件这里演示使用 element-ui 组件上传上传图片的组件需要隐藏点击图片上传时调用element-ui 的图片上传上传成功后返回图片链接。在编辑器项中配置配置项el-upload v-showfalseclassavatar-uploader:datafileUpload:show-file-listfalse:http-requestonUploadHandler/el-upload在option中配置上传操作之前的option就耀稍作修改handlers:{image:function(value){if(value){// value truedocument.querySelector(.avatar-uploader input).click()}else{this.quill.format(image,false)}}}点击富文本上的上传图片就会触发这里的handlers将操作引到upload的函数上在这个函数里面需要做的操作是将图片上传到七牛云并拿到返回的在线链接然后将图片链接插入到页面对应位置上。这里我的上传是自己封装了函数。asynconUploadHandler(e){constimageUrl上传七牛云后返回来的一串在线链接// 获取光标所在位置letquillthis.$refs.myQuillEditor.quillletlengthquill.getSelection().index// 插入图片quill.insertEmbed(length,image,imageUrl)// 调整光标到最后quill.setSelection(length1)// this.content url}6.自定义控制图片大小1安装插件npm i quill-image-resize-module-S2在文件中导入包importQuillfromquillimportImageResizefromquill-image-resize-moduleQuill.register(modules/imageResize,ImageResize)3在原本的配置项上添加与toolbar平级进行配置toolbar:{},// 调整图片大小imageResize:{displayStyles:{backgroundColor:black,border:none,color:white},modules:[Resize,DisplaySize,Toolbar]}效果7.自定义toobar样式设计//在quill中使用toolbar:{container:toolbarOptions,handlers:{**report:this.openWorkReport**}}// 方法中使用openWorkReport(){this.$emit(openWorkReport)},// 样式/* 自定义toobar样式设计 *//* 工作汇报弹窗 */.ql-snow.ql-toolbar.ql-formats.ql-report{background:url(../images/meeting/report.png)no-repeat;background-size:contain;display:inline-block;height:18px;margin:3px 5px;width:28px;}效果有关视频上传参考视频上传