|
@@ -1,62 +1,58 @@
|
1
|
|
-import React from 'react';
|
|
1
|
+import React, { useState, useRef, useEffect, useCallback } from 'react';
|
2
|
2
|
import E from 'wangeditor';
|
3
|
3
|
import PreviewMenu from './PreviewMenu'
|
4
|
4
|
import Preview from './Preview'
|
5
|
5
|
import { fetch, apis } from '../../utils/request';
|
6
|
6
|
|
7
|
|
-/**
|
8
|
|
- * @param {*} props
|
9
|
|
- * @returns
|
10
|
|
- */
|
11
|
|
-class Wangedit extends React.Component {
|
12
|
|
- constructor(props, context) {
|
13
|
|
- super(props, context);
|
14
|
|
- this.state = {
|
15
|
|
- preview: false,
|
16
|
|
- html: undefined,
|
17
|
|
- contenteditable: props.contenteditable == false ? false : true
|
18
|
|
- }
|
19
|
|
- this.editor = undefined;
|
20
|
|
- }
|
21
|
|
-
|
22
|
|
- render() {
|
23
|
|
- return (
|
24
|
|
- <>
|
25
|
|
- <div ref="editorElem" style={{ textAlign: 'left' }} />
|
26
|
|
- <Preview width={426} style={{width: '426px', height: '863px', margin: 0, padding: 0}} visible={this.state.preview} html={this.state.html} onCancel={() => this.setState({preview: false})} />
|
27
|
|
- </>
|
28
|
|
- );
|
29
|
|
- }
|
30
|
|
-
|
31
|
|
- componentDidMount() {
|
32
|
|
- const elem = this.refs.editorElem
|
33
|
|
- this.editor = new E(elem)
|
34
|
|
- // 使用 onchange 函数监听内容的变化
|
35
|
|
- this.editor.config.onchange = html => {
|
36
|
|
- this.setState({ html })
|
37
|
|
-
|
38
|
|
- if (typeof this.props.onChange === 'function') {
|
39
|
|
- this.props.onChange(html)
|
|
7
|
+export default props => {
|
|
8
|
+ const ref = useRef()
|
|
9
|
+ const editorRef = useRef()
|
|
10
|
+ const [preview, setPreview] = useState(false)
|
|
11
|
+ const [content, setContent] = useState()
|
|
12
|
+
|
|
13
|
+ // wangeditor 有bug, 初始先触发 onchange
|
|
14
|
+ const firstChanged = useRef(false)
|
|
15
|
+
|
|
16
|
+ const initEditor = useCallback(() => {
|
|
17
|
+ const editor = new E(ref.current)
|
|
18
|
+ editorRef.current = editor
|
|
19
|
+
|
|
20
|
+ // 取消自动 focus
|
|
21
|
+ editor.config.focus = false
|
|
22
|
+
|
|
23
|
+ // 触发 change
|
|
24
|
+ editor.config.onchange = html => {
|
|
25
|
+ // 规避 bug
|
|
26
|
+ if (!firstChanged.current) {
|
|
27
|
+ firstChanged.current = true
|
|
28
|
+ return
|
|
29
|
+ }
|
|
30
|
+
|
|
31
|
+ setContent(html)
|
|
32
|
+
|
|
33
|
+ if (typeof props.onChange === 'function') {
|
|
34
|
+ props.onChange(html)
|
40
|
35
|
}
|
41
|
36
|
}
|
42
|
|
- this.editor.config.zIndex = 100
|
43
|
|
- this.editor.config.uploadImgMaxLength = 1
|
44
|
|
- this.editor.config.customUploadImg = function (files, insert) {
|
|
37
|
+
|
|
38
|
+ editor.config.zIndex = 100
|
|
39
|
+
|
|
40
|
+ // 自定义图片上传
|
|
41
|
+ editor.config.uploadImgMaxLength = 1
|
|
42
|
+ editor.config.customUploadImg = function (files, insert) {
|
45
|
43
|
if (!files.length) return
|
46
|
44
|
|
47
|
45
|
const data = new FormData()
|
48
|
46
|
data.append('file', files[0])
|
49
|
|
-
|
50
|
47
|
fetch(apis.image.upload)({data}).then(insert)
|
51
|
|
- }
|
52
|
|
-
|
53
|
|
- // 扩展按钮
|
54
|
|
- this.editor.menus.extend('previewMenu', PreviewMenu)
|
55
|
|
- PreviewMenu.preview = (html) => {
|
56
|
|
- this.setState({preview: true})
|
57
|
48
|
}
|
58
|
49
|
|
59
|
|
- this.editor.config.menus = [
|
|
50
|
+ // 扩展预览按钮
|
|
51
|
+ editor.menus.extend('previewMenu', PreviewMenu)
|
|
52
|
+ PreviewMenu.preview = (html) => setPreview(true)
|
|
53
|
+
|
|
54
|
+ // 配置菜单
|
|
55
|
+ editor.config.menus = [
|
60
|
56
|
'head', // 标题
|
61
|
57
|
'bold', // 粗体
|
62
|
58
|
'fontSize', // 字号
|
|
@@ -74,10 +70,10 @@ class Wangedit extends React.Component {
|
74
|
70
|
'redo', // 重复
|
75
|
71
|
'previewMenu'
|
76
|
72
|
]
|
77
|
|
-
|
|
73
|
+
|
78
|
74
|
// 过滤 word 字符
|
79
|
|
- this.editor.config.pasteFilterStyle = false
|
80
|
|
- this.editor.config.pasteTextHandle = function(content) {
|
|
75
|
+ editor.config.pasteFilterStyle = false
|
|
76
|
+ editor.config.pasteTextHandle = content => {
|
81
|
77
|
const regs = [
|
82
|
78
|
/<!--\[if [\s\S]*?endif\]-->/ig,
|
83
|
79
|
/<[a-zA-Z0-9]+\:[^>]+>[^>]*<\/[a-zA-Z0-9]+\:[^>]+>/ig,
|
|
@@ -91,32 +87,33 @@ class Wangedit extends React.Component {
|
91
|
87
|
}, content)
|
92
|
88
|
}
|
93
|
89
|
|
94
|
|
- this.editor.create()
|
95
|
|
- this.editor.$textElem.attr('contenteditable',this.state.contenteditable);
|
96
|
|
- this.editor.config.uploadImgShowBase64 = true
|
97
|
|
- this.editor.txt.html(this.props.value)
|
98
|
|
- }
|
|
90
|
+ editor.create()
|
|
91
|
+ editor.$textElem.attr('contenteditable', props.contenteditable !== false)
|
99
|
92
|
|
100
|
|
- componentDidUpdate(props, state) {
|
101
|
|
- if (this.props.value && !state.html) {
|
102
|
|
- if (this.editor) {
|
103
|
|
- this.editor.txt.html(this.props.value)
|
104
|
|
- }
|
105
|
|
- }
|
106
|
|
- }
|
107
|
|
-
|
108
|
|
- /**
|
109
|
|
- *增加这个 shouldComponentUpdate 生命函数
|
110
|
|
- 处理自动聚焦到富文本上
|
111
|
|
- *
|
112
|
|
- * @param {*} nextProps
|
113
|
|
- * @returns
|
114
|
|
- * @memberof Wangedit
|
115
|
|
- */
|
116
|
|
- shouldComponentUpdate(nextProps) {
|
117
|
|
- return nextProps.value !== this.editor.txt.html() || nextProps.preview !== this.state.preview
|
118
|
|
- }
|
119
|
|
-}
|
|
93
|
+ return () => editor.destroy()
|
|
94
|
+ }, [props.contenteditable])
|
120
|
95
|
|
121
|
|
-export default Wangedit
|
|
96
|
+ useEffect(() => {
|
|
97
|
+ initEditor()
|
|
98
|
+ }, [])
|
|
99
|
+
|
|
100
|
+ useEffect(() => {
|
|
101
|
+ if (props.value !== content && editorRef.current) {
|
|
102
|
+ setContent(props.value)
|
|
103
|
+ editorRef.current.txt.html(props.value)
|
|
104
|
+ }
|
|
105
|
+ }, [props.value])
|
122
|
106
|
|
|
107
|
+ return (
|
|
108
|
+ <>
|
|
109
|
+ <div ref={ref} style={{ textAlign: 'left' }} />
|
|
110
|
+ <Preview
|
|
111
|
+ width={426}
|
|
112
|
+ style={{width: '426px', height: '863px', margin: 0, padding: 0}}
|
|
113
|
+ visible={preview}
|
|
114
|
+ html={props.value}
|
|
115
|
+ onCancel={() => setPreview(false)}
|
|
116
|
+ />
|
|
117
|
+ </>
|
|
118
|
+ )
|
|
119
|
+}
|