it-roy-ru.com

Как можно использовать CKEditor с React.js таким образом, чтобы React мог его распознать?

Я пытался использовать componentWillMount и componentDidMount для инициализации CKEditor из контекста React, но, похоже, он не работает независимо от того, какую комбинацию я пытаюсь использовать. Кто-нибудь нашел решение этой проблемы, кроме переключения редакторов?

12
Slbox

Я опубликовал пакет на Npm для использования CKEditor с React. Для интеграции в ваш проект требуется всего 1 строка кода. 

Ссылка на Github - https://github.com/codeslayer1/react-ckeditor .

Как пользоваться?

  • Установите пакет, используя npm install react-ckeditor-component --save.
  • Затем включите компонент в приложение React и передайте ему свой контент и любые другие необходимые вам реквизиты (все реквизиты перечислены на странице Github) - 

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

Пакет использует сборку по умолчанию CKEditor, но вы также можете использовать пользовательскую сборку вместе с любыми плагинами, которые вам нравятся. Это также включает пример приложения. Надеюсь, вы найдете это полезным.

17
codeslayer1

Мудрец описывает потрясающее решение в своем ответе. Это было спасение жизни, так как я только начал использовать React, и мне это было нужно, чтобы все заработало. Однако я изменил реализацию, также включив предложения Джареда (используя 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));
  }
}

Пожалуйста, обратите внимание, что для этого также необходимо передать уникальный идентификатор:

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

Это для компонента React, который отображает параграф P текста. Если пользователь хочет отредактировать текст в абзаце, он может щелкнуть по нему, чтобы затем прикрепить экземпляр CKEditor. Когда пользователь завершает изменение текста в экземпляре редактора, возникает событие «размытия», которое передает данные 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 в консоли. 

Надеюсь это поможет

6
Sage

Просто укажите ckeditor.js в index.html и используйте его с window.CKEDITOR. Не используйте CKEDITOR прямо как документ в компоненте React. 

Просто прочитайте первую строку ckeditor.js, вы найдете, что насчет определения CKEDITOR.

1
xiongkailing

Благодаря 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} />
0
David Silva