介绍

wangEditor4 —— 轻量级 web 富文本编辑器,配置方便,使用简单。

浏览器兼容性

兼容常见的 PC 浏览器:Chrome,Firefox,Safari,Edge,QQ 浏览器,IE11。

不支持移动端。

封装wangEditor组件

一、引入wangeditor

1
npm i wangeditor@4.7.15 --save

二、使用

简单使用

components文件夹下新建文件夹WangEditor,再在WangEditor文件夹下新建config.js文件,用来存放默认配置,写入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const defaultConfig = {
menus: [
'head', // 标题
'bold', // 加粗
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'indent', // 缩进
'lineHeight', // 行高
'foreColor', // 字体颜色
'backColor', // 背景色
'link', // 链接
'list', // 序列
// 'todo', // 待办事项
'justify', // 对齐
'quote', // 引用
// 'emoticon', // 表情
'image', // 图片
'video', // 视频
// 'table', // 表格
// 'code', // 代码
'splitLine', // 分割线
'undo', // 撤销
'redo' // 恢复
],
fontNames: [
'黑体',
'仿宋',
'楷体',
'宋体',
'微软雅黑',
'Arial'
], // 常用字体
lineHeights: ['1', '1.15', '1.6', '2', '2.5', '3'],
uploadImgAccept: ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'], // 限制图片类型
uploadVideoAccept: ['mp4'] // 限制视频类型
};
export default {
defaultConfig
};

WangEditor文件夹下新建index.vue文件,写入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<template>
<div>
<div ref="editor">
</div>
</div>
</template>

<script>
import WangEditor from 'wangeditor';
import config from './config';

export default {
name: 'WangEditor',
data() {
return {
editorE: '', // 编辑器的对象
};
},
props: {
value: {
type: String,
default: ''
},
// 编辑器高度
height: {
type: Number,
default: 200
},
// 限制图片大小 M
uploadImgMaxSize: {
type: Number,
default: 5
},
// 限制视频大小 M
uploadVideoMaxSize: {
type: Number,
default: 500
},
placeholder: {
type: String,
default: '请输入内容...'
},
config: {
default: () => {
return {};
}
}
},
computed: {
needConfig() {
return { ...config.defaultConfig, ...this.config };
}
},
watch: {
value(val) { // 普通的watch监听
if (val !== this.editorE.txt.html()) {
this.editorE.txt.html(val);
}
}
},
mounted() {
const that = this;
// 初始化编辑框
that.init();
// 窗口发生变化,重新初始化编辑器,这里做节流操作
window.addEventListener('resize', () => {
that.editorE.destroy(); // 销毁
that.editorE = null;
that.init();
});
},
beforeDestroy() {
// 销毁编辑器
this.editorE.destroy();
this.editorE = null;
},
methods: {
init() {
const that = this;
/* 实例化 */
that.editorE = new WangEditor(that.$refs.editor);
// 设置富文本的高度
that.editorE.config.height = that.height;
// 取消自动 focus
that.editorE.config.focus = false;
// 配置菜单
that.editorE.config.menus = that.needConfig.menus;
// 配置字体
that.editorE.config.fontNames = that.needConfig.fontNames;
// 默认提示
that.editorE.config.placeholder = that.placeholder;
// 配置全屏功能 默认全屏
that.editorE.config.showFullScreen = true;
// 配置行高
that.editorE.config.lineHeights = that.needConfig.lineHeights;
// 设置菜单栏提示为上标还是下标
that.editorE.config.menuTooltipPosition = 'down';
// 配置element ui message提示
that.editorE.config.customAlert = (s, t) => {
switch (t) {
case 'success':
that.$message.success(s);
break;
case 'info':
that.$message.info(s);
break;
case 'warning':
that.$message.warning(s);
break;
case 'error':
that.$message.error(s);
break;
default:
that.$message.info(s);
break;
}
};
// 创建编辑器
that.editorE.create();
that.$nextTick(() => {
// 绑定值
that.editorE.txt.html(this.value);
});
// 监控编辑器内容变化,同步更新到文本 向上传递更新
that.editorE.config.onchange = function(html) {
that.$emit('input', html);
};
}
}
};
</script>
<style scoped lang="scss">
::v-deep .w-e-toolbar {
border-color: #d4d4d4 !important;
}

::v-deep .w-e-text-container {
border-color: #d4d4d4 !important;
}
</style>

图片上传

① 使用wangeditor实现的上传方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 图片上传
// 隐藏插入网络图片功能
that.editorE.config.showLinkImg = false;
// 配置 server 接口地址
that.editorE.config.uploadImgServer = 'xxx';
// 默认限制图片大小是 5M
that.editorE.config.uploadImgMaxSize = that.uploadImgMaxSize * 1024 * 1024;
// 限制图片类型
that.editorE.config.uploadImgAccept = that.needConfig.uploadImgAccept;
// 自定义上传的参数
that.editorE.config.uploadFileName = 'file';
// 自定义头部token信息
that.editorE.config.uploadImgHeaders = {};
// 限制一次最多能传几张图片
that.editorE.config.uploadImgMaxLength = 1;
// 设置请求参数
that.editorE.config.uploadImgParams = {};
// timeout 即上传接口等待的最大时间,默认是 10 秒钟,可以自己修改
that.editorE.config.uploadImgTimeout = 10 * 1000;
// 回调函数
that.editorE.config.uploadImgHooks = {
// 上传图片之前
before(xhr) {
console.log(xhr);
// 可阻止图片上传
// return {
// prevent: true,
// msg: '需要提示给用户的错误信息'
// }
},
// 图片上传并返回了结果,图片插入已成功
success(xhr) {
console.log('success', xhr);
},
// 图片上传并返回了结果,但图片插入时出错了
fail(xhr, editor, resData) {
that.$message.error('插入图片失败');
console.log('fail', resData);
},
// 上传图片出错,一般为 http 请求的错误
error(xhr, editor, resData) {
that.$message.error('上传图片出错');
console.log('error', xhr, resData);
},
// 上传图片超时
timeout(xhr) {
that.$message.error('上传图片超时');
console.log('timeout');
},
// 图片上传并返回了结果,想要自己把图片插入到编辑器中
// 例如服务器端返回的不是 { errno: 0, data: [...] } 这种格式,可使用 customInsert
async customInsert(insertImgFn, result) {
// result 即服务端返回的接口
const imgUrl = result.url;
// insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
insertImgFn(imgUrl);
}
};
②自己实现图片上传,如上传图片到某个云服务器
1
2
3
4
5
6
7
that.editorE.config.customUploadImg = function (resultFiles, insertImgFn) {
// resultFiles 是 input 中选中的文件列表
// insertImgFn 是获取图片 url 后,插入到编辑器的方法

// 上传图片,返回结果,将图片插入到编辑器中
insertImgFn(imgUrl)
}

视频上传

视频上传建议不要使用wangeditor自带的上传方式,改用自定义上传。因为视频文件普遍较大,且自带的上传回调函数里面,没有上传中阶段的信息反馈,让用户等得很焦虑。所以这里自定义视频上传,给用户一个上传进度反馈。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<template>
<div style="position: relative">
<div ref="editor">
</div>
<div v-if="dataUploading" class="tips-progress">
<!-- el-ui进度条组件 -->
<el-progress
style="width: 60%"
:text-inside="true"
:stroke-width="18"
:percentage="uploadProgress"
:color="customColors"
status="success">
</el-progress>
</div>
</div>
</template>

<script>
......

import axios from 'axios'

export default {
data() {
return {
editorE: '', // 编辑器的对象
dataUploading: false,
uploadProgress: 0,
customColors: [
{
color: '#f56c6c',
percentage: 20
},
{
color: '#e6a23c',
percentage: 40
},
{
color: '#5cb87a',
percentage: 60
},
{
color: '#1989fa',
percentage: 80
},
{
color: '#6f7ad3',
percentage: 100
}
]
......
};
},

......

methods: {
init() {
......
// 视频上传
// 隐藏插入网络视频功能
that.editorE.config.showLinkVideo = false;
// 限制视频大小
that.editorE.config.uploadVideoMaxSize = that.uploadVideoMaxSize * 1024 * 1024;
// 限制视频类型
that.editorE.config.uploadVideoAccept = that.needConfig.uploadVideoAccept;
// 自定义视频上传
that.editorE.config.customUploadVideo = function(resultFiles, insertVideoFn) {
that.uploadProgress = 0;
// 显示进度条
that.dataUploading = true;
const file = resultFiles[0];
axios.post('xxxx', file, {
onUploadProgress: progressEvent => {
// 视频上传进度
const percent = (progressEvent.loaded / progressEvent.total * 100) | 0;
that.uploadProgress = percent
}
})
.then(res => {
const { status, data } = res;
// 不管上没上传成功都关闭进度条
that.dataUploading = false;
if(status === 201){
insertVideoFn(data.url);
} else {
that.$message.error('视频上传失败');
}
});
};
}
}
};
</script>
<style scoped lang="scss">
.tips-progress {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
line-height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 100000;
display: flex;
align-items: center;
justify-content: center;
}

::v-deep .w-e-toolbar {
border-color: #d4d4d4 !important;
}

::v-deep .w-e-text-container {
border-color: #d4d4d4 !important;
}
</style>

自定义菜单-一键排版

怎么自定义菜单可以看官方文档,这里不多说,在WangEditor文件夹下新建wLayoutMenu.js文件,写入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import E from 'wangeditor';

const { $, BtnMenu } = E;

// 设置默认样式
const initPStyle = 'text-indent: 2em; font-size: 20px !important; line-height: 1.5; font-family: 仿宋';
export default class wLayoutMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = $('<div class="w-e-menu" style="width: 80px;font-weight: bold;color: #999" data-title="一键排版">一键排版</div>');
super($elem, editor);
}

clickHandler() {
// 获取富文本编辑区的DOM
const childDomArr = this.editor.$textElem.elems[0].childNodes;
if (childDomArr.length > 0) {
childDomArr.forEach(item => {
// 富文本编辑的内容默认外层都是由p标签包容,所以直接在p标签上进行设置默认排版的样式
if (item.nodeName === 'P') {
item.style.cssText = initPStyle;
}
if (item.childNodes.length > 0) {
// 遍历找到子元素中存在img标签的内容进行设置默认样式
item.childNodes.forEach(child => {
if (child.localName === 'img') {
// 获取原图width、height
const width = child.width;
const height = child.height;
const ratio = width / height;
const setW = 600;
let setH = 0; // 等比计算
if (setW / setH !== ratio) {
setH = setW / ratio;
}
// 给img标签设置行内样式
child.setAttribute('width', setW);
child.setAttribute('height', setH);
child.style.cssText = 'text-align: center';
}
});
}
});
}
}

// 菜单是否被激活(如果不需要,这个函数可以空着)
tryChangeActive() {
}
}

index.vue引入使用

1
import wLayoutMenu from './wLayoutMenu';
1
2
3
4
5
6
7
init() {
......
// 注册菜单
that.editorE.menus.extend('shortcutLayout', wLayoutMenu);
// 配置菜单
that.editorE.config.menus = that.needConfig.menus;
}

config.js 中配置一键排版的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
menus: [
'head', // 标题
'bold', // 加粗
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'indent', // 缩进
'lineHeight', // 行高
'foreColor', // 字体颜色
'backColor', // 背景色
'link', // 链接
'list', // 序列
// 'todo', // 待办事项
'justify', // 对齐
'quote', // 引用
// 'emoticon', // 表情
'image', // 图片
'video', // 视频
// 'table', // 表格
// 'code', // 代码
'splitLine', // 分割线
'undo', // 撤销
'redo' // 恢复
'shortcutLayout' // 一键排版 放在最后面,也可以放在其他位置
],

粘贴处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 关闭粘贴样式的过滤
that.editorE.config.pasteFilterStyle = false;
// 自定义处理粘贴的文本内容
that.editorE.config.pasteTextHandle = function(pasteStr) {
// 对粘贴的文本进行处理,然后返回处理后的结果
// 这里处理图片,给粘贴的图片宽度设置一个最大宽度100%,视频同理
const htmlDom = document.createElement('div');
htmlDom.innerHTML = pasteStr;
const imgDomArr = htmlDom.querySelectorAll('img[src]');
imgDomArr.forEach(img => {
img.style.maxWidth = '100%';
});
const result = htmlDom.innerHTML;
htmlDom.remove();
return result;
};

el-ui form表单内容验证

参考el-input组件,当输入框失去焦点的时候要触发表单验证,怎么触发我们这个自定义组件的表单验证呢?我们可以写入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
< script >
import emitter from 'element-ui/src/mixins/emitter';
export default {
mixins: [emitter],
data() {
return {
......
focused: false,
}
},
methods: {
init() {
.......
// 失去焦点处理
that.editorE.config.onblur = function (newHtml) {
// 用于el-form表单验证,具体参考el-input
if (that.focused) {
that.focused = false;
that.dispatch('ElFormItem', 'el.form.blur', [newHtml]);
}
};
// 聚焦处理
that.editorE.config.onfocus = function () {
that.focused = true;
};
}
}
} <
/script>

三、完整代码

config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const defaultConfig = {
menus: [
'head', // 标题
'bold', // 加粗
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'indent', // 缩进
'lineHeight', // 行高
'foreColor', // 字体颜色
'backColor', // 背景色
'link', // 链接
'list', // 序列
// 'todo', // 待办事项
'justify', // 对齐
'quote', // 引用
// 'emoticon', // 表情
'image', // 图片
'video', // 视频
// 'table', // 表格
// 'code', // 代码
'splitLine', // 分割线
'undo', // 撤销
'redo' // 恢复
// 'shortcutLayout' // 一键排版
],
fontNames: [
'黑体',
'仿宋',
'楷体',
'宋体',
'微软雅黑',
'Arial'
], // 字体
lineHeights: ['1', '1.15', '1.6', '2', '2.5', '3'],
uploadImgAccept: ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'], // 限制图片类型
uploadVideoAccept: ['mp4'] // 限制视频类型
};
export default {
defaultConfig
};

wLayoutMenu.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import E from 'wangeditor';

const { $, BtnMenu } = E;

// 设置默认样式
const initPStyle = 'text-indent: 2em; font-size: 20px !important; line-height: 1.5; font-family: 仿宋';
export default class wLayoutMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = $('<div class="w-e-menu" style="width: 80px;font-weight: bold;color: #999" data-title="一键排版">一键排版</div>');
super($elem, editor);
}

clickHandler() {
// 获取富文本编辑区的DOM
const childDomArr = this.editor.$textElem.elems[0].childNodes;
if (childDomArr.length > 0) {
childDomArr.forEach(item => {
// 富文本编辑的内容默认外层都是由p标签包容,所以直接在p标签上进行设置默认排版的样式
if (item.nodeName === 'P') {
item.style.cssText = initPStyle;
}
if (item.childNodes.length > 0) {
// 遍历找到子元素中存在img标签的内容进行设置默认样式
item.childNodes.forEach(child => {
if (child.localName === 'img') {
// 获取原图width、height
const width = child.width;
const height = child.height;
const ratio = width / height;
const setW = 600;
let setH = 0; // 等比计算
if (setW / setH !== ratio) {
setH = setW / ratio;
}
// 给img标签设置行内样式
child.setAttribute('width', setW);
child.setAttribute('height', setH);
child.style.cssText = 'text-align: center';
}
});
}
});
}
}

// 菜单是否被激活(如果不需要,这个函数可以空着)
tryChangeActive() {
}
}

index.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
<template>
<div style="position: relative" :style="pareStyle">
<div ref="editor">
</div>
<div v-if="dataUploading" class="tips-progress">
<el-progress
style="width: 60%"
:text-inside="true"
:stroke-width="$px(18)"
:percentage="uploadProgress"
:color="customColors"
status="success">
</el-progress>
</div>
</div>
</template>

<script>
import WangEditor from 'wangeditor';
import config from './config';
import wLayoutMenu from './wLayoutMenu';
import emitter from 'element-ui/src/mixins/emitter';
import axios from 'axios'

export default {
name: 'WangEditor',
mixins: [emitter],
data() {
return {
editorE: '', // 编辑器的对象
dataUploading: false,
uploadProgress: 0,
pareStyle: {},
focused: false,
customColors: [
{
color: '#f56c6c',
percentage: 20
},
{
color: '#e6a23c',
percentage: 40
},
{
color: '#5cb87a',
percentage: 60
},
{
color: '#1989fa',
percentage: 80
},
{
color: '#6f7ad3',
percentage: 100
}
]
};
},
props: {
value: {
type: String,
default: ''
},
height: {
type: Number,
default: 200
},
// M
uploadImgMaxSize: {
type: Number,
default: 5
},
// M
uploadVideoMaxSize: {
type: Number,
default: 500
},
placeholder: {
type: String,
default: '请输入内容...'
},
config: {
default: () => {
return {};
}
}
},
computed: {
needConfig() {
return { ...config.defaultConfig, ...this.config };
}
},
watch: {
value(val) { // 普通的watch监听
if (val !== this.editorE.txt.html()) {
this.editorE.txt.html(val);
}
}
},
mounted() {
const that = this;
// 初始化编辑框
that.init();
window.addEventListener('resize', () => {
that.editorE.destroy();
that.editorE = null;
that.pareStyle = {};
that.init();
});
},
beforeDestroy() {
// 销毁编辑器
this.editorE.destroy();
this.editorE = null;
},
methods: {
init() {
const that = this;
/* 实例化 */
that.editorE = new WangEditor(that.$refs.editor);
// 设置富文本的高度
that.editorE.config.height = that.height;
// 取消自动 focus
that.editorE.config.focus = false;
// 注册菜单
that.editorE.menus.extend('shortcutLayout', wLayoutMenu);
// 配置菜单
that.editorE.config.menus = that.needConfig.menus;
// 配置字体
that.editorE.config.fontNames = that.needConfig.fontNames;
// 默认提示
that.editorE.config.placeholder = that.placeholder;
// 配置全屏功能 默认全屏
that.editorE.config.showFullScreen = true;
// 配置行高
that.editorE.config.lineHeights = that.needConfig.lineHeights;
// 设置菜单栏提示为上标还是下标
that.editorE.config.menuTooltipPosition = 'down';
// 配置element ui message提示
that.editorE.config.customAlert = (s, t) => {
switch (t) {
case 'success':
that.$message.success(s);
break;
case 'info':
that.$message.info(s);
break;
case 'warning':
that.$message.warning(s);
break;
case 'error':
that.$message.error(s);
break;
default:
that.$message.info(s);
break;
}
};

// 图片上传
// 隐藏插入网络图片功能
that.editorE.config.showLinkImg = false;
// 默认限制图片大小是 5M
that.editorE.config.uploadImgMaxSize = that.uploadImgMaxSize * 1024 * 1024;
// 限制图片类型
that.editorE.config.uploadImgAccept = that.needConfig.uploadImgAccept;
// 限制一次最多能传几张图片
that.editorE.config.uploadImgMaxLength = 1;
that.editorE.config.customUploadImg = function(resultFiles, insertImgFn) {
that.uploadProgress = 0;
that.dataUploading = true;
const file = resultFiles[0];
axios.post('xxxx', file, {
onUploadProgress: progressEvent => {
// 图片上传进度
const percent = (progressEvent.loaded / progressEvent.total * 100) | 0;
that.uploadProgress = percent
}
})
.then(res => {
const { status, data } = res;
// 不管上没上传成功都关闭进度条
that.dataUploading = false;
if(status === 201){
insertImgFn(data.url);
} else {
that.$message.error('图片上传失败');
}
});
}

// 视频上传
// 隐藏插入网络视频功能
that.editorE.config.showLinkVideo = false;
// 限制视频大小
that.editorE.config.uploadVideoMaxSize = that.uploadVideoMaxSize * 1024 * 1024;
// 限制视频类型
that.editorE.config.uploadVideoAccept = that.needConfig.uploadVideoAccept;
// 自定义视频上传,由于视频一般较大,需要显示进度,就不用编辑器定义的上传了
that.editorE.config.customUploadVideo = function(resultFiles, insertVideoFn) {
that.uploadProgress = 0;
that.dataUploading = true;
const file = resultFiles[0];
axios.post('xxxx', file, {
onUploadProgress: progressEvent => {
// 视频上传进度
const percent = (progressEvent.loaded / progressEvent.total * 100) | 0;
that.uploadProgress = percent
}
})
.then(res => {
const { status, data } = res;
// 不管上没上传成功都关闭进度条
that.dataUploading = false;
if(status === 201){
insertVideoFn(data.url);
} else {
that.$message.error('视频上传失败');
}
});
};

// 粘贴处理
// 关闭粘贴样式的过滤
that.editorE.config.pasteFilterStyle = false;
// 自定义处理粘贴的文本内容
that.editorE.config.pasteTextHandle = function(pasteStr) {
// 对粘贴的文本进行处理,然后返回处理后的结果
const htmlDom = document.createElement('div');
htmlDom.innerHTML = pasteStr;
const imgDomArr = htmlDom.querySelectorAll('img[src]');
imgDomArr.forEach(img => {
img.style.maxWidth = '100%';
});
const result = htmlDom.innerHTML;
htmlDom.remove();
return result;
};
// 创建编辑器
that.editorE.create();
that.$nextTick(() => {
const offsetHeight = that.$refs.editor.offsetHeight;
const offsetWidth = that.$refs.editor.offsetWidth;
that.pareStyle = {
height: `${offsetHeight}px`,
width: `${offsetWidth}px`
};
that.editorE.txt.html(this.value);
});
// 监控变化,同步更新到文本 向上传递更新
that.editorE.config.onchange = function(html) {
that.$emit('input', html);
};
// 失去焦点处理
that.editorE.config.onblur = function(newHtml) {
// 用于el-form表单验证,具体参考el-input
if (that.focused) {
that.focused = false;
that.dispatch('ElFormItem', 'el.form.blur', [newHtml]);
}
};
// 聚焦处理
that.editorE.config.onfocus = function() {
that.focused = true;
};
}
}
};
</script>
<style scoped lang="scss">
.tips-progress {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
line-height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 100000;
display: flex;
align-items: center;
justify-content: center;
}

::v-deep .w-e-toolbar {
border-color: #d4d4d4 !important;
}

::v-deep .w-e-text-container {
border-color: #d4d4d4 !important;
}
</style>