React Typescript 标签详细信息 onclick 未显示在 sun 编辑器上

React Typescript tag details onclick not showing on the sun editor

我正在使用我的 React TypeScript 项目进行 Ant 设计,

这是我的冲突,我想点击标签并将其显示为 Sun editor content area 所以当我点击标签时显示文本区域但我不能添加太阳编辑器 有什么解决办法吗? 谢谢

stazkblitz here

代码在这里

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Comment, Avatar, Form, Button, List, Input,Tag } from 'antd';
import moment from 'moment';
import 'suneditor/dist/css/suneditor.min.css';
import SunEditor from "suneditor-react";
const { TextArea } = Input;

const CommentList = ({ comments }) => (
  <List
    dataSource={comments}
    header={`${comments.length} ${comments.length > 1 ? 'replies' : 'reply'}`}
    itemLayout="horizontal"
    renderItem={props => <Comment {...props} />}
  />
);

const Editor = ({ onChange, onSubmit, submitting, value }) => (
  <>
    <Form.Item>
      <TextArea rows={4} onChange={onChange} value={value} />
    </Form.Item>
    <Form.Item>
      <Button htmlType="submit" loading={submitting} onClick={onSubmit} type="primary">
        Add Comment
      </Button>
    </Form.Item>
  </>
);

class App extends React.Component {
  state = {
    comments: [],
    submitting: false,
    value: '',
  };

  handleSubmit = () => {
    if (!this.state.value) {
      return;
    }

    this.setState({
      submitting: true,
    });

    setTimeout(() => {
      this.setState({
        submitting: false,
        value: '',
        comments: [
          ...this.state.comments,
          {
            author: 'Han Solo',
            avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
            content: <p>{this.state.value}</p>,
            datetime: moment().fromNow(),
          },
        ],
      });
    }, 1000);
  };

  handleChange = e => {
    this.setState({
      value: e.target.value,
    });
  };

  addTag = e => {
    const txt = e.target.innerHTML;
    this.setState(prevState => ({
      ...prevState,
      value: `${prevState.value} <${txt}> `,
    }));
  }

  render() {
    const { comments, submitting, value } = this.state;

    return (
      <>

       <div>
      <Tag onClick={this.addTag} color="magenta">First Name</Tag>
      <Tag onClick={this.addTag} color="red">Last Name</Tag>
      <Tag onClick={this.addTag} color="volcano">NIC</Tag>
      <Tag onClick={this.addTag} color="orange">FAX</Tag>
    
    </div>
        {comments.length > 0 && <CommentList comments={comments} />}
        <Comment
          avatar={
            <Avatar
              src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
              alt="Han Solo"
            />
          }
          content={
            <Editor
              onChange={this.handleChange}
              onSubmit={this.handleSubmit}
              submitting={submitting}
              value={value}
            />
          }
        />

        <SunEditor

                                                        autoFocus={true}
                                                        width="100%"
                                                        height="150px"
                                                        onChange={this.handleChange}
                                                        onClick={this.onSubmit}
                                           /*       defaultValue={value}*/
                                                        setOptions={{
                                                            buttonList: [
                                                                // default
                                                                ['undo', 'redo'],
                                                                ['bold', 'underline', 'italic', 'list'],
                                                                ['table', 'link', 'image'],
                                                                ['fullScreen'],
                                                                ['codeView']
                                                            ]

                                                        }}
                                                    

                                                        setContents={value}
                                                    />

      </>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('container'));


  [1]: https://www.npmjs.com/package/suneditor-react
  [2]: https://stackblitz.com/edit/react-pqp2iu-ynivmu?file=index.js

2021 年 5 月 13 日更新

在 sun 编辑器中使用状态会触发 handleChange()addTag() 之间的竞争问题,状态有可能被旧状态替换。

要摆脱它,请使用 sun 编辑器参考来操作内容。

为了添加新文本并将其水平放置而不是垂直放置,他们有一个 insertHTML() 功能,该功能将尊重 html 内容而不首先添加新的 <p>

更新代码: https://stackblitz.com/edit/react-pqp2iu-axacak?file=index.js

  • 创建 editorRef
constructor() {
  super();
  this.editorRef = React.createRef();
}
  • 将 ref 应用到 sun editor
<SunEditor ref={this.editorRef} ... />
  • 去掉handleChange(),交给sun editor自己处理
  • 使用 insertHTML()
  • 附加文本
addTag = e => {
    const txt = e.target.innerHTML;
    this.editorRef.current.editor.insertHTML(`{${txt}}`);
};

旧内容

<> 在 sun 文本编辑器中有特殊含义,代表 html 标签,如 <p> <a> 等,它将被隐藏编辑器。

因此,当您将 <Firtname> 应用到编辑器时,它就会消失。为了能够显示它,我建议您使用 SendGrid、Twilio 模板也使用的 mustache 语法 {}

除此之外,handleChange 在 sun 文本编辑器中将 return 直接向您提供内容,因此无需从事件目标中获取它。

这是你的带有小胡子模板的分叉版本

https://stackblitz.com/edit/react-pqp2iu-axacak?file=index.js

handleChange = content => {
    console.log(content);
    this.setState({
      value: content
    });
};

addTag = e => {
    const txt = e.target.innerHTML;
    console.log(txt);
    this.setState(prevState => ({
      ...prevState,
      value: prevState.value.replace(/<\/p>$/, '') + `{${txt}}</p>` // remove the last </p>, append the new content, add back the </p> to avoid new line
    }));
};