组件引入:
1 <qill-editor-component
2 :serviceDetail="service.serviceContent"
3 @getDetailFn="getDetail"
4 :disabledEdit="disabled"
5 ></qill-editor-component>
组件内容:
1 <template> 2 <div class="editor"> 3 <!-- 图片上传组件辅助--> 4 <!-- 如果你需要手动控制数据流,需要像这样手动监听changed事件 --> 5 6 <quill-editor 7 v-model="content" 8 ref="myQuillEditor" 9 :options="editorOption" 10 outPut="html" 11 @blur="onEditorBlur($event)" 12 @focus="onEditorFocus($event)" 13 @change="onEditorChange($event)" 14 @selection-change="selectionChange" 15 :style="{ height: '88vh', '100%'}" 16 class="junScrollBar" 17 > 18 <!-- 自定义toolar --> 19 <div id="toolbar" slot="toolbar"> 20 <button class="ql-bold" title="加粗">Bold</button> 21 <button class="ql-italic" title="斜体">Italic</button> 22 <button class="ql-underline" title="下划线">underline</button> 23 <button class="ql-strike" title="删除线">strike</button> 24 <button class="ql-blockquote" title="引用"></button> 25 <button class="ql-code-block" title="代码"></button> 26 <button class="ql-header" value="1" title="标题1"></button> 27 <button class="ql-header" value="2" title="标题2"></button> 28 <button class="ql-list" value="ordered" title="有序列表"></button> 29 <button class="ql-list" value="bullet" title="无序列表"></button> 30 <select class="ql-header" title="段落格式"> 31 <option selected>段落</option> 32 <option value="1">标题1</option> 33 <option value="2">标题2</option> 34 <option value="3">标题3</option> 35 <option value="4">标题4</option> 36 <option value="5">标题5</option> 37 <option value="6">标题6</option> 38 </select> 39 <select class="ql-size" title="字体大小"> 40 <option value="10px">10px</option> 41 <option value="12px">12px</option> 42 <option value="14px">14px</option> 43 <option value="16px" selected>16px</option> 44 <option value="18px">18px</option> 45 <option value="20px">20px</option> 46 <option value="20px">24px</option> 47 <option value="20px">30px</option> 48 </select> 49 <select class="ql-font" title="字体"> 50 <option value="SimSun">宋体</option> 51 <option value="SimHei">黑体</option> 52 <option value="Microsoft-YaHei">微软雅黑</option> 53 <option value="KaiTi">楷体</option> 54 <option value="FangSong">仿宋</option> 55 <option value="Arial">Arial</option> 56 </select> 57 <select class="ql-color" value="color" title="字体颜色"></select> 58 <select class="ql-background" value="background" title="背景颜色"></select> 59 <select class="ql-align" value="align" title="对齐"></select> 60 <button class="ql-clean" title="还原"></button> 61 <button class="ql-link" title="超链接"></button> 62 <button class="ql-image" title="图片"></button> 63 <!-- <button class="ql-video" title="视频"></button> --> 64 </div> 65 </quill-editor> 66 <el-upload 67 class="ueUpload" 68 :action="serverUrl" 69 name="img" 70 ref="upload" 71 :data="uploadUeData" 72 :headers="header" 73 :show-file-list="false" 74 :on-success="uploadSuccess" 75 :on-error="uploadError" 76 :before-upload="uploadbefore" 77 accept="image/png, image/jpeg, image/gif, image/jpg" 78 ></el-upload> 79 </div> 80 </template> 81 <script> 82 import { Quill, quillEditor } from "vue-quill-editor"; 83 import "quill/dist/quill.core.css"; 84 import "quill/dist/quill.snow.css"; 85 import "quill/dist/quill.bubble.css"; 86 87 // 自定义字体大小 88 let Size = Quill.import("attributors/style/size"); 89 Size.whitelist = ["10px", "12px", "14px", "16px", "18px", "20px"]; 90 Quill.register(Size, true); 91 // 自定义字体类型 92 var fonts = [ 93 "SimSun", 94 "SimHei", 95 "Microsoft-YaHei", 96 "KaiTi", 97 "FangSong", 98 "Arial", 99 "Times-New-Roman", 100 "sans-serif", 101 "宋体", 102 "黑体" 103 ]; 104 var Font = Quill.import("formats/font"); 105 Font.whitelist = fonts; 106 Quill.register(Font, true); 107 108 export default { 109 name: "ueEditor", 110 components: { 111 quillEditor 112 }, 113 props: { 114 // 编辑器内容 115 serviceDetail: { 116 type: String, 117 default: "" 118 }, 119 disabledEdit: { 120 type: Boolean, 121 default: "" 122 } 123 }, 124 data() { 125 return { 126 // content: "", 127 content: "", 128 // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示 129 quillUpdateImg: false, 130 str: "", 131 editorOption: { 132 theme: "snow", 133 placeholder: "", 134 modules: { 135 toolbar: { 136 container: "#toolbar", 137 handlers: { 138 image: function(value) { 139 if (value) { 140 // 触发input框选择图片文件 141 document.querySelector(".ueUpload input").click(); 142 } else { 143 this.quill.format("image", false); 144 } 145 } 146 // link: function(value) { 147 // if (value) { 148 // var href = prompt('请输入url'); 149 // this.quill.format("link", href); 150 // } else { 151 // this.quill.format("link", false); 152 // } 153 // }, 154 } 155 } 156 } 157 }, 158 // 要上传的图片的服务器地址 159 serverUrl: "", 160 header: { 161 // token: sessionStorage.token 162 }, // 有的图片服务器要求请求头需要有token 163 addRange: [], 164 uploadUeData: { 165 file: "", 166 project: "JINXINSERVE_WEB" 167 }, 168 photoUrl: "", // 上传图片地址 169 uploadType: "", // 上传的文件类型(图片、视频 170 html: "" 171 }; 172 }, 173 // 如果你需要得到当前的editor对象来做一些事情,你可以像下面这样定义一个方法属性来获取当前的editor对象,实际上这里的$refs对应的是当前组件内所有关联了ref属性的组件元素对象 174 computed: { 175 editor() { 176 return this.$refs.myQuillEditor.quill; 177 } 178 }, 179 created() {}, 180 watch: { 181 serviceDetail(val) { 182 this.content = val; 183 } 184 }, 185 mounted() { 186 // this.editor.getModule("toolbar").addHandler("image", this.imgHandler); 187 // this.editor.getModule("toolbar").addHandler("video", this.videoHandler); 188 let content = ""; // 请求后台返回的内容字符串 189 this.str = this.escapeStringHTML(content); 190 this.initEditor(); 191 }, 192 193 // 如果需要手动控制数据同步,父组件需要显式地处理changed事件 194 methods: { 195 initEditor() { 196 // 如果是查看,编辑栏点击无效果 197 if (this.disabledEdit) { 198 document.getElementById("toolbar").style.pointerEvents = "none"; 199 } 200 }, 201 escapeStringHTML(str) { 202 str = str.replace(/</g, "<"); 203 str = str.replace(/>/g, ">"); 204 return str; 205 }, 206 // 图片上传之前调取的函数 207 // 这个钩子还支持 promise 208 // 富文本图片上传前 209 uploadbefore(file) { 210 // 显示loading动画 211 this.quillUpdateImg = true; 212 this.uploadUeData.file = file; 213 }, 214 215 onEditorBlur(editor) {}, 216 onEditorFocus(editor) { 217 // 富文本获得焦点时的事件 218 if (this.disabledEdit) { 219 editor.enable(false); // 在获取焦点的时候禁用 220 } 221 }, 222 onEditorChange({ editor, html, text }) { 223 // 当编辑器文本发生变化, this。content可以试试获取到当前编辑器内的文本内容 224 this.content = html; 225 // console.log("内容:", this.content); 226 this.$emit("getDetailFn", this.content); 227 }, 228 // 点击图片ICON触发事件 229 imgHandler(state) { 230 this.addRange = this.editor.getSelection(); 231 if (state) { 232 let fileInput = document.getElementById("imgInput"); 233 fileInput.click(); // 加一个触发事件 234 } 235 this.uploadType = "image"; 236 }, 237 // 点击视频ICON触发事件 238 videoHandler(state) { 239 this.addRange = this.editor.getSelection(); 240 if (state) { 241 let fileInput = document.getElementById("imgInput"); 242 fileInput.click(); // 加一个触发事件 243 } 244 this.uploadType = "video"; 245 }, 246 uploadSuccess(res, file) { 247 // res为图片服务器返回的数据 248 // 获取富文本组件实例 249 let quill = this.$refs.myQuillEditor.quill; 250 // 如果上传成功 251 if (res.code == 200) { 252 console.log("ue", res); 253 // 获取光标所在位置 254 let length = quill.getSelection().index; 255 // 插入图片 res.url为服务器返回的图片地址 256 quill.insertEmbed(length, "image", res.url); 257 // 调整光标到最后 258 quill.setSelection(length + 1); 259 } else { 260 this.$message.error("图片插入失败"); 261 } 262 // loading动画消失 263 this.quillUpdateImg = false; 264 }, 265 // 富文本图片上传失败 266 uploadError() { 267 // loading动画消失 268 this.quillUpdateImg = false; 269 this.$message.error("图片插入失败"); 270 }, 271 // 20190920 添加 272 selectionChange(editor, range) { 273 if (range) { 274 if (range.start !== range.end) { 275 this.selectedText = editor.getText(range.start, range.end); 276 editor.formatText(range, "custom", "hello world"); 277 } 278 } 279 } 280 } 281 }; 282 </script> 283 <style lang="scss"> 284 .editor { 285 border: 1px solid #ccc; 286 border-radius: 5px; 287 box-shadow: 0 1px 2px #ccc; 288 289 .ql-toolbar { 290 border: none; 291 border-bottom: 1px solid #ccc; 292 border-radius: 5px; 293 box-shadow: 1px 1px 2px #ccc; 294 } 295 296 .ql-container { 297 border: none; 298 } 299 .ql-editor { 300 height: 89%; 301 } 302 } 303 </style>