Javascript CKEditor 如何以允许 React 识别的方式与 React.js 一起使用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36535234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:12:17  来源:igfitidea点击:

How can CKEditor be used with React.js in a way that allows React to recognize it?

javascriptreactjsckeditorecmascript-6

提问by Slbox

I've tried using componentWillMount and componentDidMount to initialize CKEditor from within the context of React, but it doesn't seem to work no matter what combination I try. Has anyone found a solution to this besides switching editors?

我已经尝试使用 componentWillMount 和 componentDidMount 从 React 的上下文中初始化 CKEditor,但无论我尝试哪种组合,它似乎都不起作用。除了切换编辑器之外,有没有人找到解决方案?

回答by codeslayer1

I published a package on Npm for using CKEditor with React. It takes just 1 line of code to integrate in your project.

我在 Npm 上发布了一个包,用于将 CKEditor 与 React 结合使用。只需 1 行代码即可集成到您的项目中。

Github link - https://github.com/codeslayer1/react-ckeditor.

Github 链接 - https://github.com/codeslayer1/react-ckeditor

How to Use?

如何使用?

  • Install the package using npm install react-ckeditor-component --save.
  • Then include the component in your React app and pass it your content and any other props that you need(all props listed on Github page) -
  • 使用npm install react-ckeditor-component --save.
  • 然后在你的 React 应用程序中包含该组件,并将你的内容和任何其他你需要的道具(所有道具都列在 Github 页面上)传递给它 -

<CKEditor activeClass="editor" content={this.state.content} onChange={this.updateContent} />

<CKEditor activeClass="editor" content={this.state.content} onChange={this.updateContent} />

The package uses the default build of CKEditor but you can use a custom build as well along with any of the plugins you like. It also includes a sample application. Hope you will find it useful.

该软件包使用 CKEditor 的默认构建,但您也可以使用自定义构建以及您喜欢的任何插件。它还包括一个示例应用程序。希望你会发现它很有用。

回答by Sander Verhagen

Sage describes an awesome solution in his answer. It was a lifesaver, as I've only just started using React, and I needed it to get this going. I did, however, change the implementation, also incorporating Jared's suggestions (using componentDidMount). Also, my need was to have a change callback, like so:

Sage 在他的回答中描述了一个很棒的解决方案。这是一个救星,因为我才刚刚开始使用 React,我需要它来实现这一目标。然而,我确实改变了实现,也结合了 Jared 的建议(使用componentDidMount)。另外,我需要有一个更改回调,如下所示:

Usage of the component:

组件的使用:

<CKEditor value={this.props.value} onChange={this.onChange}/>

Added this to index.html:

将此添加到index.html

<script src="//cdn.ckeditor.com/4.6.1/basic/ckeditor.js"></script>

Using the following component code:

使用以下组件代码:

import React, {Component} from "react";

export default class CKEditor extends Component {
  constructor(props) {
    super(props);
    this.componentDidMount = this.componentDidMount.bind(this);
  }

  render() {
    return (
      <textarea name="editor" cols="100" rows="6" defaultValue={this.props.value}></textarea>
    )
  }

  componentDidMount() {
    let configuration = {
      toolbar: "Basic"
    };
    CKEDITOR.replace("editor", configuration);
    CKEDITOR.instances.editor.on('change', function () {
      let data = CKEDITOR.instances.editor.getData();
      this.props.onChange(data);
    }.bind(this));
  }
}

Again, all credits to Sage!

再次,所有学分都归功于 Sage!



The following is an improved version of the basic version above, which supports multiple CKEditor instances on the same page:

以下是上述基础版的改进版,支持同一个页面多个CKEditor实例:

import React, {Component} from "react";

export default class CKEditor extends Component {
  constructor(props) {
    super(props);
    this.elementName = "editor_" + this.props.id;
    this.componentDidMount = this.componentDidMount.bind(this);
  }

  render() {
    return (
      <textarea name={this.elementName} defaultValue={this.props.value}></textarea>
    )
  }

  componentDidMount() {
    let configuration = {
      toolbar: "Basic"
    };
    CKEDITOR.replace(this.elementName, configuration);
    CKEDITOR.instances[this.elementName].on("change", function () {
      let data = CKEDITOR.instances[this.elementName].getData();
      this.props.onChange(data);
    }.bind(this));
  }
}

Please note that this requires some unique ID to be passed along as well:

请注意,这还需要传递一些唯一的 ID:

<CKEditor id={...} value={this.props.value} onChange={this.onChange}/>

回答by Sage

This is for a React component which displays a P paragraph of text. If the user wants to edit the text in the paragraph, they can click it which will then attach a CKEditor instance. When the user is done altering the text in the Editor instance, the "blur" event fires which transfers the CKEditor data to a state property and destroys the CKEditor Instance.

这是用于显示 P 段文本的 React 组件。如果用户想要编辑段落中的文本,他们可以单击它,然后附加一个 CKEditor 实例。当用户完成编辑器实例中的文本更改时,“blur”事件将触发,将 CKEditor 数据传输到状态属性并销毁 CKEditor 实例。

import React, {PropTypes, Component} from 'react';

export default class ConditionalWYSIWYG extends Component {
    constructor(props) {
        super(props);
        this.state = {
            field_name:this.props.field_name,
            field_value:this.props.field_value,
            showWYSIWYG:false
        };
        this.beginEdit = this.beginEdit.bind(this);
        this.initEditor = this.initEditor.bind(this);
    }
    render() {
        if ( this.state.showWYSIWYG  ) {
            var field = this.state.field_name;
            this.initEditor(field);
            return (
                <textarea name='editor' cols="100" rows="6" defaultValue={unescape(this.state.field_value)}></textarea>
            )
        } else {
            return (
                <p className='description_field' onClick={this.beginEdit}>{unescape(this.state.field_value)}</p>
            )
        }
    }
    beginEdit() {
        this.setState({showWYSIWYG:true})
    }
    initEditor(field) {
        var self = this;

        function toggle() {
            CKEDITOR.replace("editor", { toolbar: "Basic", width: 870, height: 150 });
            CKEDITOR.instances.editor.on('blur', function() {

                let data = CKEDITOR.instances.editor.getData();
                self.setState({
                    field_value:escape(data),
                    showWYSIWYG:false
                });
                self.value = data;
                CKEDITOR.instances.editor.destroy();
            });
        }
        window.setTimeout(toggle, 100);
    }
}

The self.value = dataallows me to retrieve the text from the parent component via a simple ref

self.value = data让我通过一个简单的参考检索父组件中的文本

The window.setTimeout();gives React time to do what it does. Without this delay, I would get an Cannot read property 'getEditor' of undefinederror in the console.

window.setTimeout();给了 React 时间来做它所做的事情。如果没有这个延迟,我会Cannot read property 'getEditor' of undefined在控制台中收到 错误消息。

Hope this helps

希望这可以帮助

回答by xiongkailing

Just refer the ckeditor.jsin index.html, and use it with window.CKEDITOR. Don't use CKEDITORstraight like the document in React component.

只需引用ckeditor.jsin index.html,并将其与window.CKEDITOR. 不要CKEDITOR像 React 组件中的文档那样直接使用。

Just read the first-line of ckeditor.js, you will find what about define of CKEDITOR.

只需阅读ckeditor.js的第一行,您就会发现CKEDITOR的定义是什么。

回答by David Silva

Thanks to Sage, Sander & co. I just wanted to contribute a version for the "inline" mode of CKEditor.

感谢 Sage、Sander & co。我只是想为 CKEditor 的“内联”模式贡献一个版本。

First, disable CKEditor's "auto-inline" behavior with...

首先,禁用 CKEditor 的“自动内联”行为...

CKEDITOR.disableAutoInline = true

Then, for the actual component...

然后,对于实际组件...

import React, {Component} from 'react';

export default class CKEditor extends Component {
    constructor(props) {
        super(props);
        this.elementName = "editor_" + this.props.id;
        this.componentDidMount = this.componentDidMount.bind(this);
        this.onInput = this.onInput.bind(this);
    }

    onInput(data) {
        console.log('onInput: ' + data);
    }

    render() {
        return (
            <div 
                contentEditable={true} 
                suppressContentEditableWarning
                className="rte"
                id={this.elementName}> 
                {this.props.value}</div>
        )
    }

    componentDidMount() {
        let configuration = {
            toolbar: "Basic"
        };
        CKEDITOR.inline(this.elementName, configuration);
        CKEDITOR.instances[this.elementName].on("change", function() {
            let data = CKEDITOR.instances[this.elementName].getData();
            this.onInput(data);
        }.bind(this));
    }
}

Usage would be something like this:

用法是这样的:

<CKEditor id="102" value="something" onInput={this.onInput} />