最近用vue+element-ui开发一套后台管理系统,其中项目中须要用到富文本编辑器,这里总结下开发过程当中遇到的坑和使用方法。
刚开始用的是vue-quill-editor结合element-ui上传图片到服务器,name问题来了 按照官方文档上面的方式。下面是个人代码php
<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>vue
那么咱们须要怎样将富文本图片上传这个按钮跟自定义的文件上传作绑定呢。
很简单,咱们须要在editorOption配置中这么写 export default {
data() {element-ui
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>session
<script id="editor" type="text/plain"></script>
</div>
</template>app
<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里文件能够上传可是提示上传失败,这样上传的图片无法回显 有些仍是不清楚的,或者有其余更好实现效果的方法的伙伴能够跟我留言,欢迎共同进步