wangEditor4富文本编辑器+vue项目组件封装详细
1.安装wangEditor(我当前用的版本是4.7.6)
yarn add wangeditor@4.7.6
//package.json
"wangeditor": "4.7.6", //版本
2.创建组件editor.vue
<template lang="html">
<div class="editor" >
<div class="editor-box" ref="allEditor" @click="focusText">
</div>
//这是我自己插入的select选择框
<div ref="select">
<el-select v-model="selectOption" class="editor-select" style="width: 200px; margin: 10px 0" @change="handleChange" clearable placeholder="插入标识">
<el-option v-for="item in identifications" :key="item.contractCode" :label="item.contractCodeName" :value="item.contractCode"></el-option>
</el-select>
</div>
</div>
</template>
<script>
import E from "wangeditor";
export default {
name: "editoritem",
data() {
return {
editor: null,
info_: null,
txt: null,
identifications: [],
insertStr: '',
selectOption: ''
};
},
model: {
prop: "value",
event: "change",
},
props: {
value: {
type: String,
default: "",
},
isClear: {
type: Boolean,
default: false,
},
},
watch: {
isClear(val) {
// 触发清除文本域内容
if (val) {
this.editor.txt.clear();
this.info_ = null;
}
},
value: function (value) {
if (value !== this.editor.txt.html()) {
this.editor.txt.html(this.value);
}
},
//value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
},
mounted() {
this.seteditor();
this.editor.txt.html(this.value);
},
methods: {
seteditor() {
const menuKey = "alertMenuKey";
this.editor = new E(this.$refs.allEditor);
const { $, BtnMenu, DropListMenu, PanelMenu, DropList, Panel, Tooltip } =
E;
// 创建 class
this.editor.config.uploadImgShowBase64 = false; // base 64 存储图片
this.editor.config.uploadImgServer =
"http://otp.cdinfotech.top/file/upload_images"; // 配置服务器端地址
this.editor.config.uploadImgHeaders = {}; // 自定义 header
this.editor.config.uploadFileName = "file"; // 后端接受上传文件的参数名
this.editor.config.uploadImgMaxSize = 2 * 1024 * 1024; // 将图片大小限制为 2M
this.editor.config.uploadImgMaxLength = 6; // 限制一次最多上传 3 张图片
this.editor.config.uploadImgTimeout = 3 * 60 * 1000; // 设置超时时间
this.editor.config.lineHeights = ["1", "1.15", "1.6", "2", "2.5", "3"]; // 配置行高
this.editor.config.pasteFilterStyle = false
let self = this;
// 创建 class
class InsertABCMenu extends BtnMenu {
constructor(editor) {
const $elem = E.$(self.$refs.select);
super($elem, editor);
}
// 菜单激活状态
tryChangeActive() {
this.active(); // 菜单激活
// this.unActive() // 菜单不激活
}
}
// 配置菜单
this.editor.config.menus = [
"head", // 标题
"bold", // 粗体
"fontSize", // 字号
"fontName", // 字体
"italic", // 斜体
"underline", // 下划线
"strikeThrough", // 删除线
"lineHeight", //行高
"indent", //缩进
"foreColor", // 文字颜色
"backColor", // 背景颜色
"link", // 插入链接
"list", // 列表
"justify", // 对齐方式
"quote", // 引用
"table", // 表格
"code", // 插入代码
"hr", //分割线
"|",
"undo", // 撤销
"redo", // 重复
"fullscreen", // 全屏
];
// 注册菜单
this.editor.menus.extend(menuKey, InsertABCMenu);
this.editor.config.menus = this.editor.config.menus.concat(menuKey);
this.editor.config.onchange = (html) => {
this.info_ = html; // 绑定当前逐渐地值
this.$emit("change", this.info_); // 将内容同步到父组件中
};
// 创建富文本编辑器
this.editor.create();
this.$forceUpdate()
},
focusText(e) {
},
handleChange(value) {
this.insertStr = value
this.$nextTick(() => {
this.editor.cmd.do('insertHTML', '<span>' + '{' + value + '}' + '</span > ')
})
},
//获取选择框下拉列表数据
getIdentifications() {
this.$http.system.identifications().then((res) => {
if (res.data && res.data.result == "success") {
let { contractCodeList } = res.data;
this.identifications = contractCodeList.map((item) => {
let str = item.contractCode
item.contractCodeName += `(${str})`;
return item;
});
}
});
},
},
created() {
this.getIdentifications()
}
};
</script>
//css样式
<style lang="scss" scoped>
.editor {
width: 100%;
position: relative;
z-index: 1000;
/deep/.w-e-toolbar {
align-items: center;
width: 100%;
border: 1px solid #ccc !important;
}
/deep/.w-e-text-container {
width: 100%;
min-height: 500px !important;
border: 1px solid #ccc !important;
}
}
</style>
4.应用editor组件
<el-form-item label="内容:" class="template-content">
<editor-bar v-if="isEditor" v-model="contractContent" :isClear="isClear"></editor-bar>
//对于子组件来说,允许自定义使用v-model时定制prop和event,v-model中的prop就是把value用作prop,input用作event,
</el-form-item>
(解释一下在自封装组件中使用v-model)
model: {
prop: "value",
event: "change",
},
props: {
value: {
type: String,
default: "",
},
isClear: {
type: Boolean,
default: false,
},
},
this.editor.config.onchange = (html) => {
this.info_ = html; // 绑定当前逐渐地值
this.$emit("change", this.info_); // 将内容同步到父组件中绑定的contractContent
};