使用 Quill 实现编辑器功能
使用到的技术:vue2、Element-ui2.0 、Quill 2.0
效果:
Quill编辑器上传文件和图片功能
1.安装 Quill 包
// npm 安装
npm install quill vue-quill-editor --save// yarn 安装
yarn add quill vue-quill-editor
完整代码
<template><div><!-- 隐藏上传组件,图片 / 文件上传复用 --><el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess":on-error="handleUploadError" name="file" :show-file-list="false" :headers="headers" ref="upload"style="display: none" v-if="type === 'url'"></el-upload><!-- 编辑器容器 --><div class="editor" ref="editor" :style="styles"></div></div>
</template><script>
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import { getToken } from "@/utils/auth";export default {name: "Editor",props: {value: { type: String, default: "" },height: { type: Number, default: null },minHeight: { type: Number, default: null },readOnly: { type: Boolean, default: false },fileSize: { type: Number, default: 5 }, // 上传文件大小限制(MB)type: { type: String, default: "url" },},data() {return {uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload",headers: { Authorization: "Bearer " + getToken() },Quill: null,currentValue: "",uploadType: "image", // 当前上传类型options: {theme: "snow",bounds: document.body,debug: "warn",modules: {toolbar: {container: [["bold", "italic", "underline", "strike"],["blockquote", "code-block"],[{ list: "ordered" }, { list: "bullet" }],[{ indent: "-1" }, { indent: "+1" }],[{ size: ["small", false, "large", "huge"] }],[{ header: [1, 2, 3, 4, 5, 6, false] }],[{ color: [] }, { background: [] }],[{ align: [] }],["clean"],['bold', 'italic', 'underline'],["link", "image", "video"], // 新增 file 按钮// ['image', 'file'] // 确保包含 file],handlers: {}},},placeholder: "请输入内容",readOnly: this.readOnly,},};},computed: {styles() {const style = {};if (this.minHeight) style.minHeight = `${this.minHeight}px`;if (this.height) style.height = `${this.height}px`;return style;},},watch: {value: {handler(val) {if (this.Quill && val !== this.currentValue) {this.currentValue = val || "";const html = this.Quill.root.innerHTML;if (html !== this.currentValue) {this.Quill.clipboard.dangerouslyPasteHTML(this.currentValue);}}},immediate: true,},},mounted() {this.init();},beforeDestroy() {this.Quill = null;},methods: {/** 初始化 Quill */init() {const editor = this.$refs.editor;this.Quill = new Quill(editor, this.options);// 初始化内容if (this.value) {this.currentValue = this.value;this.Quill.clipboard.dangerouslyPasteHTML(this.value);}// 富文本事件this.Quill.on("text-change", (delta, oldDelta, source) => {const html = this.$refs.editor.children[0].innerHTML;const text = this.Quill.getText();this.currentValue = html;this.$emit("input", html);this.$emit("on-change", { html, text, quill: this.Quill });this.$emit("on-text-change", delta, oldDelta, source);});this.Quill.on("selection-change", (range, oldRange, source) => {this.$emit("on-selection-change", range, oldRange, source);});this.Quill.on("editor-change", (eventName, ...args) => {this.$emit("on-editor-change", eventName, ...args);});// 如果是 URL 类型(即后端上传)if (this.type === "url") {const toolbar = this.Quill.getModule("toolbar");/** 图片上传按钮 */toolbar.addHandler("image", (value) => {console.log("image");this.uploadType = "image";if (value) {this.$refs.upload.$children[0].$refs.input.accept = "image/*";this.$refs.upload.$children[0].$refs.input.click();}});/** 文件上传按钮 */toolbar.addHandler("link", (value) => {this.uploadType = "file";if (value) {this.$refs.upload.$children[0].$refs.input.accept =".pdf,.doc,.docx,.xls,.xlsx,.txt";this.$refs.upload.$children[0].$refs.input.click();}});}},/** 上传前校验 */handleBeforeUpload(file) {console.log("handleBeforeUpload");if (this.fileSize) {const isLt = file.size / 1024 / 1024 < this.fileSize;if (!isLt) {this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);return false;}}return true;},/** 上传成功回调 */handleUploadSuccess(res, file) {const quill = this.Quill;if (res.code === 200) {const url = process.env.VUE_APP_BASE_API + res.fileName;const length = quill.getSelection(true).index;if (this.uploadType === "image") {// 插入图片quill.insertEmbed(length, "image", url);} else if (this.uploadType === "file") {// 插入文件链接const fileName = file.name;quill.insertText(length, fileName, {link: url,});}quill.setSelection(length + 1);} else {this.$message.error("文件插入失败");}},/** 上传失败回调 */handleUploadError() {this.$message.error("文件插入失败");},},
};
</script><style scoped></style>
注意:
uploadUrl:需要的地址需要修改成自己地址
headers:看自己需要是否需要添加
Quill 2.0版本中 handlers 没有监听file的事件,但是可以用 link 事件代替。
