项目背景:vue element
- 下载Kindeditor
npm i kindeditor
2.在项目的组件中封装components/kindeditor/index.vue
参考 官方文档 内置参数 也可根据项目要求进行定制化
下面代码对图片上传进行了定制 摒弃了自带的 弹窗的样式 直接现在文件的形式,把上传的文件 转化成base64进行存储 还可加一些校验!!!
<template>
<div class="kindeditor">
<textarea :id="id" name="content" v-model="outContent" placeholder="请输入"></textarea>
<input
@change="selectedFile"
style="visibility: hidden;height:0;"
type="file"
name
id="inputFile"
/>
</div>
</template>
<script>
import \'kindeditor/kindeditor-all.js\'
import \'kindeditor/lang/zh-CN.js\'
import \'kindeditor/themes/default/default.css\'
export default {
name: \'kindeditor\',
data () {
return {
editor: null,
outContent: this.content
}
},
props: {
content: {
type: String,
default: \'\'
},
id: {
type: String,
required: true
},
width: {
type: String
},
height: {
type: String
},
minWidth: {
type: Number,
default: 650
},
minHeight: {
type: Number,
default: 100
},
items: {
type: Array,
default: function () {
return [
\'source\', \'|\', \'undo\', \'redo\', \'|\', \'preview\', \'print\', \'template\', \'code\', \'cut\', \'copy\', \'paste\',
\'plainpaste\', \'wordpaste\', \'|\', \'justifyleft\', \'justifycenter\', \'justifyright\',
\'justifyfull\', \'insertorderedlist\', \'insertunorderedlist\', \'indent\', \'outdent\', \'subscript\',
\'superscript\', \'clearhtml\', \'quickformat\', \'selectall\', \'|\', \'fullscreen\', \'/\',
\'formatblock\', \'fontname\', \'fontsize\', \'|\', \'forecolor\', \'hilitecolor\', \'bold\',
\'italic\', \'underline\', \'strikethrough\', \'lineheight\', \'removeformat\', \'|\', \'image\', \'multiimage\',
\'flash\', \'media\', \'insertfile\', \'table\', \'hr\', \'emoticons\', \'baidumap\', \'pagebreak\',
\'anchor\', \'link\', \'unlink\', \'|\', \'about\'
]
}
},
noDisableItems: {
type: Array,
default: function () {
return [\'source\', \'fullscreen\']
}
},
filterMode: {
type: Boolean,
default: true
},
htmlTags: {
type: Object,
default: function () {
return {
font: [\'color\', \'size\', \'face\', \'.background-color\'],
span: [\'style\'],
div: [\'class\', \'align\', \'style\'],
table: [\'class\', \'border\', \'cellspacing\', \'cellpadding\', \'width\', \'height\', \'align\', \'style\'],
\'td,th\': [\'class\', \'align\', \'valign\', \'width\', \'height\', \'colspan\', \'rowspan\', \'bgcolor\', \'style\'],
a: [\'class\', \'href\', \'target\', \'name\', \'style\'],
embed: [\'src\', \'width\', \'height\', \'type\', \'loop\', \'autostart\', \'quality\',
\'style\', \'align\', \'allowscriptaccess\', \'/\'],
img: [\'src\', \'width\', \'height\', \'border\', \'alt\', \'title\', \'align\', \'style\', \'/\'],
hr: [\'class\', \'/\'],
br: [\'/\'],
\'p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6\': [\'align\', \'style\'],
\'tbody,tr,strong,b,sub,sup,em,i,u,strike\': []
}
}
},
wellFormatMode: {
type: Boolean,
default: true
},
resizeType: {
type: Number,
default: 2
},
themeType: {
type: String,
default: \'default\'
},
langType: {
type: String,
default: \'zh-CN\'
},
designMode: {
type: Boolean,
default: true
},
fullscreenMode: {
type: Boolean,
default: false
},
basePath: {
type: String
},
themesPath: {
type: String
},
pluginsPath: {
type: String,
default: \'\'
},
langPath: {
type: String
},
minChangeSize: {
type: Number,
default: 5
},
loadStyleMode: {
type: Boolean,
default: true
},
urlType: {
type: String,
default: \'\'
},
newlineTag: {
type: String,
default: \'p\'
},
pasteType: {
type: Number,
default: 2
},
dialogAlignType: {
type: String,
default: \'page\'
},
shadowMode: {
type: Boolean,
default: true
},
zIndex: {
type: Number,
default: 811213
},
useContextmenu: {
type: Boolean,
default: true
},
syncType: {
type: String,
default: \'form\'
},
indentChar: {
type: String,
default: \'\t\'
},
cssPath: {
type: [ String, Array ]
},
cssData: {
type: String
},
bodyClass: {
type: String,
default: \'ke-content\'
},
colorTable: {
type: Array
},
afterCreate: {
type: Function
},
afterChange: {
type: Function
},
afterTab: {
type: Function
},
afterFocus: {
type: Function
},
afterBlur: {
type: Function
},
afterUpload: {
type: Function
},
uploadJson: {
type: String
},
fileManagerJson: {
type: Function
},
allowPreviewEmoticons: {
type: Boolean,
default: true
},
// 本地上传
allowImageUpload: {
type: Boolean,
default: false
},
allowFlashUpload: {
type: Boolean,
default: false
},
allowMediaUpload: {
type: Boolean,
default: false
},
allowFileUpload: {
type: Boolean,
default: true
},
allowFileManager: {
type: Boolean,
default: false
},
fontSizeTable: {
type: Array,
default: function () {
return [\'9px\', \'10px\', \'12px\', \'14px\', \'16px\', \'18px\', \'24px\', \'32px\']
}
},
// 0 网络图片 1本地图片
imageTabIndex: {
type: Number,
default: 0
},
formatUploadUrl: {
type: Boolean,
default: true
},
fullscreenShortcut: {
type: Boolean,
default: false
},
extraFileUploadParams: {
type: Array,
default: function () {
return []
}
},
filePostName: {
type: String,
default: \'imgFile\'
},
fillDescAfterUploadImage: {
type: Boolean,
default: false
},
afterSelectFile: {
type: Function
},
pagebreakHtml: {
type: String,
default: \'<hr style=”page-break-after: always;” class=”ke-pagebreak” />\'
},
// 在线上传
allowImageRemote: {
type: Boolean,
default: false
},
autoHeightMode: {
type: Boolean,
default: false
},
fixToolBar: {
type: Boolean,
default: false
},
tabIndex: {
type: Number
}
},
watch: {
content (val) {
this.editor && val !== this.outContent && this.editor.html(val)
},
outContent (val) {
this.$emit(\'update:content\', val)
this.$emit(\'on-content-change\', val)
}
},
mounted () {
var _this = this
_this.editor = window.KindEditor.create(\'#\' + this.id, {
width: _this.width,
height: _this.height,
minWidth: _this.minWidth,
minHeight: _this.minHeight,
items: _this.items,
noDisableItems: _this.noDisableItems,
filterMode: _this.filterMode,
htmlTags: _this.htmlTags,
wellFormatMode: _this.wellFormatMode,
resizeType: _this.resizeType,
themeType: _this.themeType,
langType: _this.langType,
designMode: _this.designMode,
fullscreenMode: _this.fullscreenMode,
basePath: _this.basePath,
themesPath: _this.cssPath,
pluginsPath: _this.pluginsPath,
langPath: _this.langPath,
minChangeSize: _this.minChangeSize,
loadStyleMode: _this.loadStyleMode,
urlType: _this.urlType,
newlineTag: _this.newlineTag,
pasteType: _this.pasteType,
dialogAlignType: _this.dialogAlignType,
shadowMode: _this.shadowMode,
zIndex: _this.zIndex,
useContextmenu: _this.useContextmenu,
syncType: _this.syncType,
indentChar: _this.indentChar,
cssPath: _this.cssPath,
cssData: _this.cssData,
bodyClass: _this.bodyClass,
colorTable: _this.colorTable,
afterCreate: _this.afterCreate,
afterChange: function () {
_this.afterChange
_this.outContent = this.html()
},
afterTab: _this.afterTab,
afterFocus: _this.afterFocus,
afterBlur: _this.afterBlur,
afterUpload: _this.afterUpload,
uploadJson: _this.uploadJson,
fileManagerJson: _this.fileManagerJson,
allowPreviewEmoticons: _this.allowPreviewEmoticons,
allowImageUpload: _this.allowImageUpload,
allowFlashUpload: _this.allowFlashUpload,
allowMediaUpload: _this.allowMediaUpload,
allowFileUpload: _this.allowFileUpload,
allowFileManager: _this.allowFileManager,
fontSizeTable: _this.fontSizeTable,
imageTabIndex: _this.imageTabIndex,
formatUploadUrl: _this.formatUploadUrl,
fullscreenShortcut: _this.fullscreenShortcut,
extraFileUploadParams: _this.extraFileUploadParams,
filePostName: _this.filePostName,
fillDescAfterUploadImage: _this.fillDescAfterUploadImage,
afterSelectFile: _this.afterSelectFile,
pagebreakHtml: _this.pagebreakHtml,
allowImageRemote: _this.allowImageRemote,
autoHeightMode: _this.autoHeightMode,
fixToolBar: _this.fixToolBar,
tabIndex: _this.tabIndex
})
// 添加点击图片回调函数
_this.editor.clickToolbar("image", () => {
// 禁用自带的图片弹窗
this.editor.hideDialog();
// 打开文件
this.handleOpenFile();
});
},
methods:{
// 打开文件
handleOpenFile() {
let input = window.document.getElementById("inputFile");
// 解决同一个文件不能监听的问题
input.addEventListener(
"click",
function() {
this.value = "";
},
false
);
// 点击input
input.click();
},
// 图片上传
async selectedFile($event) {
const file = $event.target.files[0];
// console.log($event,file,this.file2Base64(file,res=>{console.log(res)}))
this.file2Base64(file,res=>{
this.$emit(\'base64Flie\',res)
})
},
file2Base64(file, cb){
let url = URL.createObjectURL(file);
let reader = new FileReader();
reader.onload = function (evt) {
let base64 = evt.target.result;
cb(base64);
};
reader.readAsDataURL(file);
}
}
}
</script>
- 对自定义的组件进行二次封装 views/components/kindeditor.vue
通过自定义属性 对kindeditor组件进行样式上的自定义
对组件返回的base64图片格式进行显示内容的拼接(注意直接修改prorps里text的值 是不生效的 父组件无法捕捉到值) 可参考文档
<template>
<div id="app">
<editor id="editor_id" :height="height" :width="width" :content.sync="text" :items="items"
:afterChange="afterChange"
@base64Flie="base64Flie"
:loadStyleMode="false"
@on-content-change="onContentChange"></editor>
<!-- <div> editorTextCopy: {{ editorTextCopy }} </div> -->
</div>
</template>
<script>
import editor from \'@/components/kindeditor/index.vue\'
export default {
name: \'kindeditor\',
components: {
editor
},
props:{
height: {
type: String,
default: \'500px\'
},
width: {
type: String,
default: \'700px\'
},
text: {
type: String,
default: \'\'
},
},
data () {
return {
editorText: \'直接初始化值\', // 双向同步的变量
editorTextCopy: \'\' , // content-change 事件回掉改变的对象
items: [
\'justifyleft\', \'justifycenter\', \'justifyright\',\'justifyfull\', \'insertorderedlist\', \'insertunorderedlist\', \'indent\', \'outdent\', \'subscript\',
\'superscript\', \'quickformat\', \'selectall\',
\'|\', \'fullscreen\',
\'formatblock\', \'fontname\', \'fontsize\',
\'|\', \'image\', \'forecolor\', \'hilitecolor\', \'bold\',
\'italic\', \'underline\', \'strikethrough\', \'lineheight\', \'removeformat\',
]
}
},
methods: {
onContentChange (val) {
this.editorTextCopy = val;
// window.console.log(this.editorTextCopy)
this.$emit(\'update:text\',this.editorTextCopy)
},
afterChange (e) {
console.log(e)
},
base64Flie (base64) {
this.text+=`<img src="${base64}" alt="">`
//注意
this.$emit(\'update:text\',this.text)
}
}
}
</script>
- 在表单中使用 封装好的组件 kindeditor
<template>
<div>
<el-form ref="formData" :model="formData" label-width="100px" @submit.native.prevent>
<el-row :gutter="3">
<el-col :span="24">
<el-form-item label="内容" prop="news_content" placeholder="内容"
:rules="[
{ required: true, message:\'请输入\'}
]">
<kindeditor ref="news_content" :text.sync=\'formData.news_content\' :width="\'100%\'"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script>
import kindeditor from \'./kindeditor.vue\'
export default {
props: {
formData: {
type: Object,
default: () => {
return {}
}
},
},
components:{
kindeditor
},
}
遇到的问题
1.打包上线 在点击上传图片时 会加载 refresh.png align_top.gif align_left.gif align_right.gif加载 错误的情况?
可通过修改pluginsPath的值
也可对 源码kindeditor-all.js 7221 7225 7226 7227进行注释 (在不影响需求的前提下 已解决问题优先)
碰到背景图片加载问题 修改打包文件目录