vue后台管理系统富文本组件(二)kindeditor
简介
富文本组件作为后台管理系统的最重要的基础组件之一,好多公司还是习惯使用kindeditor。虽然他的界面比较老,但是相当稳定bug少。
主要依赖说明 (先安装,步骤略)
{
"axios": "^0.18.0",
"element-ui": "2.11.1",
"vue": "^2.6.10",
"kindeditor": "^4.1.10",
}
正文
1.组件
文件目录
src/components/Kindeditor/index.vue
<template>
<div class="margin-top-20">
<textarea :id="id" name="content" v-model="outContent"></textarea>
<input
@change="selectedFile"
style="visibility: hidden;height:0;"
type="file"
name
id="inputFile"
/>
</div>
</template>
<script>
import "kindeditor/themes/default/default.css";
import "kindeditor/kindeditor-all-min.js";
import "kindeditor/lang/zh-CN.js";
// 以下四个配置文件见下文
import items from "./config/items";
import htmlTags from "./config/htmlTags";
import fontSizeTable from "./config/fontSizeTable";
import otherConfig from "./config/otherConfig";
export default {
name: "kindeditor-component",
props: {
// 编辑器内容 url
html: {
type: String,
default: ""
},
// 编辑器内容
content: {
type: String,
default: ""
},
// 编辑器id
id: {
type: String,
// required: true,
default: "kindeditor-id"
},
// 宽
width: {
type: String,
default: `100%`
},
// 高
height: {
type: String,
default: "400"
},
// 最小宽
minWidth: {
type: Number,
default: 650
},
// 最小高
minHeight: {
type: Number,
default: 400
},
// toolbar 工具栏配置
items: {
type: Array,
default: function() {
return [...items];
}
},
// 标签配置
htmlTags: {
type: Object,
default: function() {
return { ...htmlTags };
}
},
//字号配置
fontSizeTable: {
type: Array,
default: function() {
return [...fontSizeTable];
}
},
// 语言配置
langType: {
type: String,
default: "zh-CN"
},
// 主题配置
themeType: {
type: String,
default: "default"
},
// body 的样式
bodyClass: {
type: String,
default: "ke-content"
},
// 其他配置项
...otherConfig
},
data() {
return {
editor: null,
outContent: this.content
};
},
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);
this.$emit("input", val);
},
// 初始化编辑器内容
html(val) {
if (
this.html &&
(this.html.startsWith("https://") || this.html.startsWith("http://"))
) {
this.loadUrl(val);
} else {
this.outContent = "";
this.outContent ? this.editor.appendHtml(this.outContent) : "";
}
}
},
created() {
if (
this.html &&
(this.html.startsWith("https://") || this.html.startsWith("http://"))
) {
this.loadUrl(this.html);
} else {
this.outContent = "";
setTimeout(() => {
this.outContent ? this.editor.appendHtml(this.outContent) : "";
}, 1000);
}
},
mounted() {
// 初始访问时创建
this.initEditor();
// 添加焦点
// this.editor.focus();
// 添加点击图片回调函数
this.editor.clickToolbar("image", () => {
// 禁用自带的图片弹窗
this.editor.hideDialog();
// 打开文件
this.handleOpenFile();
});
},
activated() {
// keep-alive 进入时创建
this.initEditor();
},
deactivated() {
// keep-alive 离开时移除
this.removeEditor();
},
beforeDestroy() {
// 实例销毁之前移除
this.removeEditor();
},
methods: {
// 打开文件
handleOpenFile() {
let input = document.getElementById("inputFile");
// 解决同一个文件不能监听的问题
input.addEventListener(
"click",
function() {
this.value = "";
},
false
);
// 点击input
input.click();
},
// 选择好文件
async selectedFile($event) {
const file = $event.target.files[0];
// 把图片上传到后端服务器 拿到url uploadImage 是自己后端上传图片的接口
// 调用appendHtml方法把图片追加到富文本
// const url= await uploadImage (file)
// this.editor.appendHtml(
// `<img style="max-width:100%;" src="https://${data.Location}">`
// );
},
// 编辑器内容上传到cos,调用返回url
async content2Url() {
// 把html片段上传到后端服务器 拿到url uploadHtml 是自己后端上传的接口
// try {
// const res = await uploadHtml(this.outContent)
// return res
// } catch (error) {
// this.$message({
// message: error.data.message,
// type: 'error'
// })
// }
}
// 加载html填充编辑器内容
loadUrl(url) {
if (url && url.length > 0) {
axios.get(url)
.then(response => {
// 处理HTML显示
this.outContent = response.data;
this.editor.appendHtml(this.outContent);
this.$emit("subLoadUrlToHtml", response.data);
})
.catch(() => {
this.outContent = "服务器数据加载失败,请重试!";
this.editor.appendHtml(this.outContent);
});
}
},
// 移除编辑器实例
removeEditor() {
window.KindEditor.remove(`#${this.id}`);
},
// 初始化编辑器
initEditor() {
this.removeEditor();
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.themesPath,
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: () => {
this.editor ? (this.outContent = this.editor.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
});
}
}
};
</script>
<style>
</style>
src/components/Kindeditor/config/items.js
// toolbar配置
const items = [
// "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"
];
export default items;
src/components/Kindeditor/config/htmlTags.js
const htmlTags = {
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": []
};
export default htmlTags;
src/components/Kindeditor/config/fontSizeTable.js
// 字体配置
const fontSizeTable = [
"9px",
"10px",
"12px",
"14px",
"16px",
"18px",
"24px",
"32px"
];
export default fontSizeTable;
src/components/Kindeditor/config/otherConfig.js
// 其他非主要配置项
const otherConfig = {
noDisableItems: {
type: Array,
default: function() {
return ["source", "fullscreen"];
}
},
filterMode: {
type: Boolean,
default: true
},
wellFormatMode: {
type: Boolean,
default: true
},
resizeType: {
type: Number,
default: 2
},
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
},
colorTable: {
type: Array
},
afterCreate: {
type: Function
},
afterTab: {
type: Function
},
afterFocus: {
type: Function
},
afterBlur: {
type: Function
},
afterUpload: {
type: Function
},
uploadJson: {
type: String
},
fileManagerJson: {
type: String
},
allowPreviewEmoticons: {
type: Boolean,
default: true
},
allowImageUpload: {
type: Boolean,
default: true
},
allowFlashUpload: {
type: Boolean,
default: true
},
allowMediaUpload: {
type: Boolean,
default: true
},
allowFileUpload: {
type: Boolean,
default: true
},
allowFileManager: {
type: Boolean,
default: false
},
imageTabIndex: {
type: Number,
default: 0
},
formatUploadUrl: {
type: Boolean,
default: true
},
fullscreenShortcut: {
type: Boolean,
default: false
},
extraFileUploadParams: {
type: Object,
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: true
},
autoHeightMode: {
type: Boolean,
default: false
},
fixToolBar: {
type: Boolean,
default: false
},
tabIndex: {
type: Number
}
};
export default otherConfig;
2.使用
<template>
<div>
<Kind-editor ref="kindeditor" :html="html" @input="getContent"></Kind-editor>
</div>
</template>
<script>
import KindEditor from "@/components/Kindeditor";
export default {
name: 'GoodsForm',
components: {
KindEditor
},
data() {
return {
html: 'https://ebusiness-1255313385.cosbj.myqcloud.com/image/20190823/center2019082304054532.html',
content:''
}
},
methods: {
// 获取编辑器内容
getContent(content) {
this.content = content
},
// 编辑器内容转换成在线url
async getcontent2Url() {
try {
const htmlUrl = await this.$refs.kindeditor.content2Url()
return htmlUrl
} catch (error) {
console.log(error)
}
}
}
}
</script>
3.使用效果
参考链接
1.kindeditor官方文档