vue-quill-editor的大圖片上傳問題解決
阿新 • • 發佈:2020-09-01
專案中有個使用vue-quill-editor富文字編輯器的功能,當上傳大圖片時,圖片資源會被轉成base64格式,當圖片過大時字串的大小可能達到2M以上,資料庫無法儲存。
vue-quill-editor提供了一個 handlers
可以自定義圖片上傳的方式,意思是點選這個圖片按鈕的時候,會出發一個回撥,可以在回撥裡觸發自己的檔案上傳開關。這裡我用的檔案上傳是antd-vue的a-upload屬性。
quill-quill-editor:
<quill-editor v-model="message" :options="editorOption"@change="change"> <div id="toolbar" slot="toolbar"></div> </quill-editor>
引數:
editorOption: { modules: { toolbar: { container: [ ["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"], //清除字型樣式 ["image"], //上傳圖片 ], handlers: { image: (value) => { if (value) {
// 觸發antd-vue的modal對話方塊 this.visible = true; } else { this.quill.format("image", false); } }, }, }, syntax: { highlight: (text) => hljs.highlightAuto(text).value, }, }, },
說明:
- 這裡的思路是當點選圖片按鈕時,顯示antd-vue的對話方塊,上傳元件就放在對話方塊中
- 通過上傳元件選擇圖片,並通過後端給的上傳介面獲取返回的地址
- 然後把返回的地址使用字串處理把img的src動態拼接到內容中
對話方塊:
<a-modal title="選擇圖片" :visible="visible" @ok="handleOk" @cancel="handleCancel" :closable="false" okText="確定" cancelText="取消" :file-list="fileList" :before-upload="beforeUpload" > <a-upload class="pdupload" name="file" :multiple="false" :action="$api.upload" @change="handleChange1" accept=".jpg, .jpeg, .png, .webp" :fileList="fl" > <a-button> <a-icon type="upload" />選擇圖片 </a-button> <span style="padding-left: 15px;color:#888;font-size:12px;">最多一次上傳1張圖片</span> </a-upload> </a-modal>
handleChange1(info) { console.log("圖片", info); if (info.fileList.length > 1) { this.$message.warning("每次僅能上傳一張圖片!"); return; } this.fl = info.fileList; if (info.file.status !== "uploading") { console.log(info.file, info.fileList); } if (info.file.status === "done") { this.detailImage = info.file.response.response.file_url; this.$message.success(`${info.file.name}上傳成功`); } else if (info.file.status === "error") { this.$message.error(`${info.file.name}上傳失敗`); } }, handleOk() { this.visible = false; // 把圖片用img標籤的形式新增到詳情中 console.log("結束標籤所處位置", this.message.lastIndexOf("</p>")); if (this.detailImage) { let n = this.message.lastIndexOf("</p>"); let s = this.message; let s1 = s.substring(0, n); let domS = `<img src='${this.detailImage}'/></p>`; s1 += domS; this.message = s1; } // 清空已經選擇的圖片 this.fl = []; this.detailImage = ""; }, handleCancel() { this.visible = false; }
元件原始碼
<template> <div class="pro_detail"> <!-- 產品詳情元件 --> <common-tit title="產品詳情"></common-tit> <quill-editor v-model="message" :options="editorOption" @change="change"> <div id="toolbar" slot="toolbar"></div> </quill-editor> <a-modal title="選擇圖片" :visible="visible" @ok="handleOk" @cancel="handleCancel" :closable="false" okText="確定" cancelText="取消" :file-list="fileList" :before-upload="beforeUpload" > <a-upload class="pdupload" name="file" :multiple="false" :action="$api.upload" @change="handleChange1" accept=".jpg, .jpeg, .png, .webp" :fileList="fl" > <a-button> <a-icon type="upload" />選擇圖片 </a-button> <span style="padding-left: 15px;color:#888;font-size:12px;">最多一次上傳1張圖片</span> </a-upload> </a-modal> </div> </template> <script> import CommonTit from "../CommonTit"; export default { components: { CommonTit }, props: ["proDetail"], data() { return { fl: [], visible: false, previewVisible: false, detailImage: "", message: "", editorOption: { modules: { toolbar: { container: [ ["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"], //清除字型樣式 ["image"], //上傳圖片 ], handlers: { image: (value) => { if (value) { this.visible = true; } else { this.quill.format("image", false); } }, }, }, syntax: { highlight: (text) => hljs.highlightAuto(text).value, }, }, }, }; }, methods: { change() { console.log(this.message); this.$emit("update:proDetail", this.message); }, handleChange1(info) { console.log("圖片", info); if (info.fileList.length > 1) { this.$message.warning("每次僅能上傳一張圖片!"); return; } this.fl = info.fileList; if (info.file.status !== "uploading") { console.log(info.file, info.fileList); } if (info.file.status === "done") { this.detailImage = info.file.response.response.file_url; this.$message.success(`${info.file.name}上傳成功`); } else if (info.file.status === "error") { this.$message.error(`${info.file.name}上傳失敗`); } }, handleOk() { this.visible = false; // 把圖片用img標籤的形式新增到詳情中 console.log("當前內容:", this.message); console.log("結束標籤所處位置", this.message.lastIndexOf("</p>")); if (this.detailImage) { let n = this.message.lastIndexOf("</p>"); let s = this.message; let s1 = s.substring(0, n); let domS = `<img src='${this.detailImage}'/></p>`; s1 += domS; this.message = s1; } // 清空已經選擇的圖片 this.fl = []; this.detailImage = ""; }, handleCancel() { this.visible = false; }, }, mounted() { this.message = this.proDetail; }, }; </script> <style lang="scss" scoped> .pro_detail { height: 594px !important; border-bottom-width: 0; .quill-editor { text-align: left; height: 491px; >>> .ql-toolbar .ql-formats { margin-right: 0; } } >>> .ant-upload { display: flex; flex-direction: column; } } </style>