张延森 4 anos atrás
pai
commit
0d76d9cbaa
1 arquivos alterados com 71 adições e 74 exclusões
  1. 71
    74
      src/components/Wangedit/Wangedit.jsx

+ 71
- 74
src/components/Wangedit/Wangedit.jsx Ver arquivo

@@ -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
+}