最近用vue+element-ui開發一套後臺管理系統,其中項目中需要用到富文本編輯器,這裏總結下開發過程中遇到的坑和使用方法。
剛開始用的是vue-quill-editor結合element-ui上傳圖片到服務器,name問題來了 按照官方文檔上面的方式。下面是我的代碼
<template>
<div>
<!-- 圖片上傳組件輔助-->
<el-upload
class="avatar-uploader"
:action="serverUrl"
name="img"
:headers="header"
:show-file-list="false"
:on-success="uploadSuccess"
:on-error="uploadError"
:before-upload="beforeUpload">
</el-upload>
<!--富文本編輯器組件-->
<el-row v-loading="uillUpdateImg">
<quill-editor
v-model="detailContent"
ref="myQuillEditor"
:options="editorOption"
@change="onEditorChange($event)"
@ready="onEditorReady($event)"
>
</quill-editor>
</el-row>
</div>
</template>
<script>
export default {
data() {
return {
quillUpdateImg: false, // 根據圖片上傳狀態來確定是否顯示loading動畫,剛開始是false,不顯示
serverUrl: '', // 這裏寫你要上傳的圖片服務器地址
header: {token: sessionStorage.token}, // 有的圖片服務器要求請求頭需要有token之類的參數,寫在這裏
detailContent: '', // 富文本內容
editorOption: {} // 富文本編輯器配置
}
},
methods: {
// 上傳圖片前
beforeUpload(res, file) {},
// 上傳圖片成功
uploadSuccess(res, file) {},
// 上傳圖片失敗
uploadError(res, file) {}
}
}
</script>
那麼我們需要怎樣將富文本圖片上傳這個按鈕跟自定義的文件上傳做綁定呢。
很簡單,我們需要在editorOption配置中這麼寫
export default {
data() {
return {
quillUpdateImg: false, // 根據圖片上傳狀態來確定是否顯示loading動畫,剛開始是false,不顯示
serverUrl: '', // 這裏寫你要上傳的圖片服務器地址
header: {token: sessionStorage.token}, // 有的圖片服務器要求請求頭需要有token之類的參數,寫在這裏
detailContent: '', // 富文本內容
editorOption: {
placeholder: '',
theme: 'snow', // or 'bubble'
modules: {
toolbar: {
container: toolbarOptions, // 工具欄
handlers: {
'image': function (value) {
if (value) {
document.querySelector('#quill-upload input').click()
} else {
this.quill.format('image', false);
}
}
}
}
}
}
}
}
}
但是這裏問題就出現了,當你用element-ui upload方法上傳時你會發現上傳不成功,emmmm~你會發現上傳時Request Method 方式爲OPTIONS,這跟平時的提交方式不一樣,Status Code等於204,,去網上又查閱了下,發現這種請求方式,但是最終還是沒有解決掉,好像是需要後端也要相應的改下東西
所以走到這裏只能用另外一種方式去實現相同的功能了————Ueditor
第一步:先按照官方的提示 去官網下載相應的代碼,我這裏後端語言是PHP所以我下的是PHP的版本,根據需求去下載
第二步:ueditor裏除了php文件都放到static文件,這是我的目錄結構
第三步:將PHP文件放到後端去,我這邊項目是我直接放到ftp上面去的,結構如下
第四步:我這邊封裝成了一個公共組件,因爲有很多頁面需要用到
<template>
<div>
<script id="editor" type="text/plain"></script>
</div>
</template>
<script>
//import AppConfig from '@/config'
import '../../../static/ueditor/ueditor.config.js'
import '../../../static/ueditor/ueditor.all.js'
import '../../../static/ueditor/lang/zh-cn/zh-cn.js'
export default {
name: "UEditor",
props: {
id: {
type: String
},
config: {
type: Object
},
defaultMsg: {
type: String
},
},
created() {
//this.$emit('defaultMsgVlaue', this.names)
},
data() {
return {
editor: null,
names: ''
}
},
mounted() {
//初始化UE
const _this = this;
this.initEditor()
//this.editor = UE.getEditor(this.id, this.config);
// this.editor.addListener('ready', () => {
// this.editor.setContent(_this.defaultMsg);
// });
},
destoryed() {
this.editor.destory();
},
methods: {
getUEContent: function() {
return this.editor.getContent();
},
initEditor() {
let _this= this;
this.editor = UE.getEditor('editor', this.config)
//編輯器準備就緒後會觸發該事件
this.editor.addListener('ready',()=>{
//設置可以編輯
this.editor.setEnabled();
this.editor.setContent(_this.defaultMsg);
})
//編輯器內容修改時
this.selectionchange()
},
//編輯器內容修改時
selectionchange() {
this.editor.addListener('selectionchange', () => {
//this.content = this.ue.getContent()
})
}
},
activated() {
//初始化編輯器
this.initEditor()
}
}
</script>
頁面調用如下
<template>
<div id="app" class="hello">
<el-button size="primary" type="info" icon="plus" @click="openWindow">打開窗口</el-button>
<el-dialog title="新增菜單" size="small" v-model="addFormVisible" :close-on-click-modal="false">
<div>
<el-button size="primary" type="info" icon="plus" @click="getContent">獲取內容</el-button>
<UEditor :config=config ref="ueditor" :defaultMsg=defaultMsg></UEditor>
</div>
</el-dialog>
</div>
</template>
<script>
import {UEditor} from './ueditor/index.js'
export default{
name: 'hello',
components: {UEditor},
data(){
return {
config: {
/*//可以在此處定義工具欄的內容
toolbars: [
['fullscreen', 'source','|', 'undo', 'redo','|','bold', 'italic', 'underline', 'fontborder', 'strikethrough',
'|','superscript','subscript','|', 'forecolor', 'backcolor','|', 'removeformat','|', 'insertorderedlist', 'insertunorderedlist',
'|','selectall', 'cleardoc','fontfamily','fontsize','justifyleft','justifyright','justifycenter','justifyjustify','|',
'link','unlink']
],*/
autoHeightEnabled: false,
autoFloatEnabled: true, //是否工具欄可浮動
initialContent:'請輸入內容', //初始化編輯器的內容,也可以通過textarea/script給值,看官網例子
autoClearinitialContent:true, //是否自動清除編輯器初始內容,注意:如果focus屬性設置爲true,這個也爲真,那麼編輯器一上來就會觸發導致初始化的內容看不到了
initialFrameWidth: null,
initialFrameHeight: 450,
BaseUrl: '',
UEDITOR_HOME_URL: 'static/ueditor/'
},
addFormVisible: false
}
},
methods: {
openWindow: function(){
this.addFormVisible = true;
},
//獲取文檔內容
getContent: function(){
let content = this.$refs.ueditor.getUEContent();
console.log(content);
alert(content);
}
}
}
</script>
注意:在這裏封裝成一個公共組件了,但是在使用的過程中會發現,在同一頁面回顯數據到ueditor時只會渲染一次,這可怎麼辦呢,
這裏想到了用watch來監聽,然後再將數據放到ueditor裏,這裏我用的參數名是defaultMsg,代碼如下:
watch: {
'defaultMsg': {
handler(newValue, oldValue) {
//父組件param對象改變會觸發此函數
this.editor.setContent(newValue);
},
deep: true
}
}
這樣的話再同一個頁面回顯ueditor時就會實時改變,做到這裏我想着試下在其他頁面是否可以,因爲有多個路由頁面需要用到ueditor,當我在其他頁面打開ueditor時,發現ueditor加載不出來了,然後我就納悶了,然後排查了很多問題之後,終於知道是因爲每次只初始化了ueditor,但是在關閉頁面時沒有將其銷燬,所以需要在上面封裝的公共組件裏去銷燬下
destroyed() {
//銷燬編輯器實例,使用textarea代替
this.editor.destroy()
//重置編輯器,可用來做多個tab使用同一個編輯器實例
//如果要使用同一個實例,請註釋destroy()方法
// this.ue.reset()
}
這樣的話就解決了在多個路由頁面的時候ueditor不現實的問題。
第五步:配置文件上傳和回顯,我們需要在上傳圖片,並且讓上傳的圖片回顯到ueditor裏,首先先將文件ueditor/ueditor.config.js裏的serverUrl換成自己項目的服務器路徑
這裏配置之後就可以直接使用了
遇到的其他問題如下:前端代碼必須跟PHP文件放在同一個域名上,我之前是將兩塊代碼分別放到不同FTP上,這樣導致ueditor裏文件可以上傳但是提示上傳失敗,這樣上傳的圖片沒法回顯
有些還是不清楚的,或者有其他更好實現效果的方法的夥伴可以跟我留言,歡迎共同進步