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

IT技术 javascript reactjs ckeditor ecmascript-6
2021-03-31 00:30:32

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

5个回答

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

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

如何使用?

  • 使用npm install react-ckeditor-component --save.
  • 然后将组件包含在您的 React 应用程序中,并将您的内容和您需要的任何其他props(在 Github 页面上列出的所有props)传递给它 -

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

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

谢谢。在尝试将 CKEditor 集成到我的项目中时,我也偶然发现了这个问题。意识到没有处理这个的开源包,所以创建了一个。
2021-05-24 00:30:32
这为我完成了工作。我也能够进行文件浏览和上传。这个包裹是诚实的天赐之物
2021-05-31 00:30:32
@ZeGregg 不。还没有。一旦 CKEditor5 发布稳定版本,将尝试添加支持。它目前处于 alpha 阶段。
2021-06-20 00:30:32
这太酷了。尽管我个人不再需要这个,但由于它的简单性和 MIT 许可证,我将给你答案。
2021-06-22 00:30:32

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

组件的使用:

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

将此添加到index.html

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

使用以下组件代码:

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));
  }
}

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


以下是上述基础版的改进版,支持同一页面多个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));
  }
}

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

<CKEditor id={...} value={this.props.value} onChange={this.onChange}/>
@SanderVerhagen " change" 触发 React 更新的事件会导致 CKEditor 缓慢爬行。我正在寻找一种类似于“ change”但速度更快的解决方案
2021-05-31 00:30:32
惊人的!感谢更新。对于以后阅读的其他人,我最终使用了 React-RTE,但后来改用了 SlateJS,它不仅仅是即插即用,而且用途广泛。
2021-06-04 00:30:32
@ReedG.Law,我无法确认缓慢,但里程显然会有所不同,并且总是欢迎改进!
2021-06-06 00:30:32
回过头来,将“ blur”改为“ change”,因为“ blur”没有考虑在CKEditor中输入内容,然后立即提交表单(即单击按钮)。
2021-06-17 00:30:32
完美的。不多说了。谢谢!
2021-06-19 00:30:32

这是用于显示 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);
    }
}

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

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

希望这可以帮助

render 应该是一个纯函数,因此对 initEditor 的调用应该移出 render 方法,而是在 componentDidMount 和 componentDidUpdate 内部调用,因为到那时组件将已呈现到 DOM 中。这也应该消除对包装 CKEditor 初始化的 setTimeout 调用的需要。
2021-05-29 00:30:32

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

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

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

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

CKEDITOR.disableAutoInline = true

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

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));
    }
}

用法是这样的:

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