CKEditor 如何以允许 React 识别的方式与 React.js 一起使用?
How can CKEditor be used with React.js in a way that allows React to recognize it?
我试过使用 componentWillMount 和 componentDidMount 从 React 的上下文中初始化 CKEditor,但无论我尝试什么组合,它似乎都不起作用。除了切换编辑器之外,还有人找到解决方案吗?
这是用于显示 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
错误。
希望对您有所帮助
Sage 在他的回答中描述了一个很棒的解决方案。它是我的救星,因为我才刚刚开始使用 React,我需要它来实现这一目标。但是,我确实更改了实现,还采纳了 Jared 的建议(使用 componentDidMount
)。另外,我需要有一个 change 回调,像这样:
组件的用法:
<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}/>
感谢 Sage、Sander & co。我只是想为 CKEditor 的 "inline" 模式贡献一个版本。
首先,禁用 CKEditor 的 "auto-inline" 行为...
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} />
我在 Npm 上发布了一个包,用于将 CKEditor 与 React 结合使用。只需 1 行代码即可集成到您的项目中。
Github link - 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 的默认构建,但您也可以使用自定义构建以及您喜欢的任何插件。它还包括一个示例应用程序。希望你会发现它有用。
只需参考index.html
中的ckeditor.js
,与window.CKEDITOR
一起使用即可。不要像 React 组件中的文档那样直接使用 CKEDITOR
。
只看ckeditor.js的第一行,你就会发现CKEDITOR的define是怎么回事。
我试过使用 componentWillMount 和 componentDidMount 从 React 的上下文中初始化 CKEditor,但无论我尝试什么组合,它似乎都不起作用。除了切换编辑器之外,还有人找到解决方案吗?
这是用于显示 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
错误。
希望对您有所帮助
Sage 在他的回答中描述了一个很棒的解决方案。它是我的救星,因为我才刚刚开始使用 React,我需要它来实现这一目标。但是,我确实更改了实现,还采纳了 Jared 的建议(使用 componentDidMount
)。另外,我需要有一个 change 回调,像这样:
组件的用法:
<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}/>
感谢 Sage、Sander & co。我只是想为 CKEditor 的 "inline" 模式贡献一个版本。
首先,禁用 CKEditor 的 "auto-inline" 行为...
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} />
我在 Npm 上发布了一个包,用于将 CKEditor 与 React 结合使用。只需 1 行代码即可集成到您的项目中。
Github link - 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 的默认构建,但您也可以使用自定义构建以及您喜欢的任何插件。它还包括一个示例应用程序。希望你会发现它有用。
只需参考index.html
中的ckeditor.js
,与window.CKEDITOR
一起使用即可。不要像 React 组件中的文档那样直接使用 CKEDITOR
。
只看ckeditor.js的第一行,你就会发现CKEDITOR的define是怎么回事。