Vue中使用vue-quil-editor富文本编辑器+el-upload实现带图片上传到SpringBoot后台接口
場景
系統(tǒng)中經(jīng)常會用到富文本編輯器,比如新增通知和公告功能,并且需要添加上傳圖片。
?
vue-quill-editor官網(wǎng):
https://www.npmjs.com/package/vue-quill-editor
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
關(guān)注公眾號
霸道的程序猿
獲取編程相關(guān)電子書、教程推送與免費(fèi)下載。
實(shí)現(xiàn)
安裝vue-quil-editor
npm install vue-quill-editor --save引用封裝組件
這里沒有使用全局引用,要將這個富文本編輯器做成一個組件,方便引用。
所以在項(xiàng)目下的components下新建Editor目錄,在此目錄下新建index.vue,用來封裝并暴露富文本編輯器組件
引入組件需要添加如下代碼,包括ccss文件也是必須要引入的
import { quillEditor } from "vue-quill-editor"; import "quill/dist/quill.core.css"; import "quill/dist/quill.snow.css"; import "quill/dist/quill.bubble.css";然后在template中添加富文本組件
??? <quill-editorclass="editor"v-model="content"ref="quillEditor":options="editorOption"@blur="onEditorBlur($event)"@focus="onEditorFocus($event)"@change="onEditorChange($event)"></quill-editor></div>設(shè)置其菜單欄通過
:options="editorOption"對應(yīng)的菜單欄的內(nèi)容定義
????? editorOption: {placeholder: "",theme: "snow", // or 'bubble'placeholder: "請輸入內(nèi)容",modules: {toolbar: {container: toolbarOptions,handlers: {image: function(value) {if (value) {// 觸發(fā)input框選擇圖片文件document.querySelector(".quill-img input").click();} else {this.quill.format("image", false);}}}}}},注意這里的設(shè)置img菜單的點(diǎn)擊事件會觸發(fā)一個function
在方法中根據(jù)class屬性找到選擇器,此選擇器是使用的ElementUI的el-upload,會觸發(fā)其點(diǎn)擊事件
el-upload的代碼如下
??? <el-uploadclass="avatar-uploader quill-img":action="uploadImgUrl"name="file":headers="headers":show-file-list="false":on-success="quillImgSuccess":on-error="uploadError":before-upload="quillImgBefore"accept='.jpg,.jpeg,.png,.gif'></el-upload>使用el-upload進(jìn)行文件上傳到SpringBoot后臺并存儲到服務(wù)器上,以及前端回顯照片的路徑參照如下博客:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/107979828
繼續(xù)看富文本組件,其內(nèi)容的綁定通過
v-model="content"來實(shí)現(xiàn),就是組件傳遞到數(shù)據(jù)庫中存儲的內(nèi)容
存儲內(nèi)容示例:
?
所以需要提前聲明content屬性
? data() {return {content: this.value,并且將當(dāng)前控件的value賦值給content,因?yàn)檫@里是封裝的組件,在調(diào)用組件時會將數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行回顯
<Editor v-model="form.noticeContent" />然后就能在組件中this.value來獲取并賦值給富文本組件綁定的content
為了實(shí)現(xiàn)監(jiān)視這兩個的改變而改變,所以添加watch函數(shù)
? watch: {value: function() {this.content = this.value;}},然后就是設(shè)置其一些事件
????? @blur="onEditorBlur($event)"@focus="onEditorFocus($event)"@change="onEditorChange($event)"如果需要對這些事件進(jìn)行操作可在下面進(jìn)行重寫
??? onEditorBlur() {//失去焦點(diǎn)事件},onEditorFocus() {//獲得焦點(diǎn)事件},onEditorChange() {//內(nèi)容改變事件this.$emit("input", this.content);},上面關(guān)聯(lián)了標(biāo)題欄中的圖片的點(diǎn)擊事件會執(zhí)行el-upload的點(diǎn)擊事件。
那么在el-upload組件中
:action="uploadImgUrl"設(shè)置其上傳的url
:headers="headers"綁定請求頭
????? headers: {Authorization: 'Bearer ' + getToken()}請求頭里攜帶token,請求頭的設(shè)置參考如下
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108345222
再設(shè)置它的一些事件
????? :on-success="quillImgSuccess":on-error="uploadError":before-upload="quillImgBefore"對上傳前,上傳成功和失敗的事件進(jìn)行重寫
??? // 富文本圖片上傳前quillImgBefore(file) {let fileType = file.type;if(fileType === 'image/jpeg' || fileType === 'image/png'){return true;}else {this.$message.error('請插入圖片類型文件(jpg/jpeg/png)');return false;}},quillImgSuccess(res, file) {// res為圖片服務(wù)器返回的數(shù)據(jù)// 獲取富文本組件實(shí)例let quill = this.$refs.quillEditor.quill;// 如果上傳成功if (res.code == 200) {// 獲取光標(biāo)所在位置let length = quill.getSelection().index;// 插入圖片? res.url為服務(wù)器返回的圖片地址quill.insertEmbed(length, "image", res.url);// 調(diào)整光標(biāo)到最后quill.setSelection(length + 1);} else {this.$message.error("圖片插入失敗");}},// 富文本圖片上傳失敗uploadError() {// loading動畫消失this.$message.error("圖片插入失敗");}注意這里的圖片上傳成功是事件中,圖片上傳對應(yīng)的后臺SpringBoot接口
??? @PostMapping("/common/upload")public AjaxResult uploadFile(MultipartFile file) throws Exception {try {// 上傳文件路徑String filePath = RuoYiConfig.getUploadPath();// 上傳并返回新文件名稱String fileName = FileUploadUtils.upload(filePath, file);String url = serverConfig.getUrl() + fileName;AjaxResult ajax = AjaxResult.success();ajax.put("fileName", fileName);ajax.put("url", url);return ajax;} catch (Exception e) {return AjaxResult.error(e.getMessage());}}在此接口中
String filePath = RuoYiConfig.getUploadPath();是在application.yml中獲取配置的文件上傳的路徑
然后調(diào)用了文件上傳工具類的上傳方法
String fileName = FileUploadUtils.upload(filePath, file);最終后臺接口返回的url是一個在服務(wù)器上絕對路徑的圖片地址,比如
http://localhost:8080/profile/upload/2020/09/02/e070fd1a26dca6c00acf6db1bc467905.png
然后
??????? // 獲取光標(biāo)所在位置let length = quill.getSelection().index;// 插入圖片? res.url為服務(wù)器返回的圖片地址quill.insertEmbed(length, "image", res.url);// 調(diào)整光標(biāo)到最后quill.setSelection(length + 1);調(diào)用
quill.insertEmbed(length, "image", res.url);就能實(shí)現(xiàn)在富文本中插入照片,插入成功后的富文本編輯器的內(nèi)容中就會增加
<img src="http://localhost:8080/profile/upload/2020/09/02/e070fd1a26dca6c00acf6db1bc467905.png ">富文本編輯器封裝組件的完整代碼
<template><div><!-- 圖片上傳組件輔助 --><el-uploadclass="avatar-uploader quill-img":action="uploadImgUrl"name="file":headers="headers":show-file-list="false":on-success="quillImgSuccess":on-error="uploadError":before-upload="quillImgBefore"accept='.jpg,.jpeg,.png,.gif'></el-upload><!-- 富文本組件 --><quill-editorclass="editor"v-model="content"ref="quillEditor":options="editorOption"@blur="onEditorBlur($event)"@focus="onEditorFocus($event)"@change="onEditorChange($event)"></quill-editor></div> </template><script> import { getToken } from '@/utils/auth'// 工具欄配置 const toolbarOptions = [["bold", "italic", "underline", "strike"],?????? // 加粗 斜體 下劃線 刪除線["blockquote", "code-block"],??????????????????? // 引用? 代碼塊[{ list: "ordered" }, { list: "bullet" }],?????? // 有序、無序列表[{ indent: "-1" }, { indent: "+1" }],??????????? // 縮進(jìn)[{ size: ["small", false, "large", "huge"] }],?? // 字體大小[{ header: [1, 2, 3, 4, 5, 6, false] }],???????? // 標(biāo)題[{ color: [] }, { background: [] }],???????????? // 字體顏色、字體背景顏色[{ 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: {/* 編輯器的內(nèi)容 */value: {type: String},/* 圖片大小 */maxSize: {type: Number,default: 4000 //kb}},components: { quillEditor },data() {return {content: this.value,uploadImgUrl: "",editorOption: {placeholder: "",theme: "snow", // or 'bubble'placeholder: "請輸入內(nèi)容",modules: {toolbar: {container: toolbarOptions,handlers: {image: function(value) {if (value) {// 觸發(fā)input框選擇圖片文件document.querySelector(".quill-img input").click();} else {this.quill.format("image", false);}}}}}},uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上傳的圖片服務(wù)器地址headers: {Authorization: 'Bearer ' + getToken()}};},watch: {value: function() {this.content = this.value;}},methods: {onEditorBlur() {//失去焦點(diǎn)事件},onEditorFocus() {//獲得焦點(diǎn)事件},onEditorChange() {//內(nèi)容改變事件this.$emit("input", this.content);},// 富文本圖片上傳前quillImgBefore(file) {let fileType = file.type;if(fileType === 'image/jpeg' || fileType === 'image/png'){return true;}else {this.$message.error('請插入圖片類型文件(jpg/jpeg/png)');return false;}},quillImgSuccess(res, file) {// res為圖片服務(wù)器返回的數(shù)據(jù)// 獲取富文本組件實(shí)例let quill = this.$refs.quillEditor.quill;// 如果上傳成功if (res.code == 200) {// 獲取光標(biāo)所在位置let length = quill.getSelection().index;// 插入圖片? res.url為服務(wù)器返回的圖片地址quill.insertEmbed(length, "image", res.url);// 調(diào)整光標(biāo)到最后quill.setSelection(length + 1);} else {this.$message.error("圖片插入失敗");}},// 富文本圖片上傳失敗uploadError() {// loading動畫消失this.$message.error("圖片插入失敗");}} }; </script><style> .editor {line-height: normal !important;height: 192px; } .quill-img {display: none; } .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: "標(biāo)題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: "標(biāo)題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: "標(biāo)題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: "標(biāo)題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: "標(biāo)題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: "標(biāo)題6"; }.ql-snow .ql-picker.ql-font .ql-picker-label::before, .ql-snow .ql-picker.ql-font .ql-picker-item::before {content: "標(biāo)準(zhǔn)字體"; } .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>封裝完組件后就是在需要用到的頁面進(jìn)行引用,比如這里是在通知和公告的新增和編輯頁面使用。
來到此vue頁面,首先在頁面中引入該組件
import Editor from '@/components/Editor' ;然后聲明該組件
export default {name: "Notice",components: {Editor},此頁面為發(fā)布通知和公告的頁面,所以在新增和編輯時的位置添加該組件
????????? <el-col :span="24"><el-form-item label="內(nèi)容"><Editor v-model="form.noticeContent" /></el-form-item></el-col>這里的form.noticeContent就是在點(diǎn)擊編輯頁面時從后臺數(shù)據(jù)庫中查詢的保存的富文本編輯器的內(nèi)容。
設(shè)計(jì)一個公告的數(shù)據(jù)庫,添加存儲內(nèi)容的字段
?
這樣就能實(shí)現(xiàn)富文本編輯器的內(nèi)容的存儲和回顯以及帶照片的上傳。
總結(jié)
以上是生活随笔為你收集整理的Vue中使用vue-quil-editor富文本编辑器+el-upload实现带图片上传到SpringBoot后台接口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue中怎样封装与使用公共状态属性组件实
- 下一篇: html5倒计时秒杀怎么做,vue 设