假设我有一个ReactJS组件,表示包含“段落”的“文档”,每个组件都包含“句子”,我想将其呈现到contenteditable
span
中。
var paragraphData = [{
id: 1,
sentenceData: [
'Paragraph 1, Sentence 1',
'Paragraph 1, Sentence 2'
]
},{
id: 2,
sentenceData: [
'Paragraph 2, Sentence 1',
'Paragraph 2, Sentence 2'
]
}];
var Sentence = React.createClass({
render: function () {
return (<span
contenteditable="true"
onKeyDown={this.props.onKeyDown}>
{this.props.value}
</span>);
}
});
var Paragraph = React.createClass({
render: function () {
var me = this;
var sentences = this.props.sentenceData.map(function (sentenceData) {
return <Sentence value={sentenceData} onKeyDown={me.props.onKeyDown} />;
});
return <div>{sentences}</div>;
});
var Document = React.createClass({
render: function () {
var me = this;
var paragraphs = this.props.paragraphData.map(function (paragraphData) {
return <Paragraph sentences={paragraphData.sentenceData} onKeyDown={me.onKeyDown}>;
});
return <div>{paragraphs}</div>;
},
onKeyDown: function (e) {
// If "Enter" is pressed, I want to split the sentence at
// getSelection().focusOffset, update the current sentence's
// value to currentValue.substr(0, focusOffset) and insert a
// new sentence with value currentValue.substr(focusOffset),
// but how do I know which paragraph/sentences I need to
// inspect/change? Is "e.target" the only thing I have to go by?
}
});
在ReactJS中,我们的想法是让数据流动并使事件流下来。 (哪一个被称为“向上”或“向下”似乎一直在变化,但希望你知道我的意思。)
在我的onKeyDown处理程序中,我如何知道哪些模型需要应用更改?
我考虑使用.bind()
将处理程序绑定到每个模型,因为它被传递出来,但它似乎有点......错误:
我感觉我正朝着错误的方向前进 - 任何帮助都非常感激!
答案 0 :(得分:1)
绑定onKeyDown函数非常好。
如果您在shouldComponentUpdate
中实施Sentence
,那么当您的应用再次呈现时,将不会再次创建绑定的功能,因为如果这些组件没有更改,它们将无法呈现。
我认为1000或10000函数的内存开销不会产生太大影响,除非遇到性能问题,否则不应尝试对其进行优化。你不想要的是每次渲染时都创建所有这些函数,这就是shouldComponentUpdate
在这里的原因。
它们不会将它们已经存在的组件耦合得更多(它们是因为它们已经在明确定义的业务环境中进行了交互)。基本上,您可以创建一个通用的,非耦合组件,它将接收任何数据,并且在关键数据呈现时,会将该数据注入回调。它是通用的,不添加耦合,您可以控制组件外部的整个行为。
请注意,绑定函数来自props或in循环到dom事件侦听器不是React禁止的,实际上你可以找到完成它的例子。
请注意,在React中,禁止重新绑定组件的函数,因为React将所有函数绑定到其组件。
因此,如果某个函数位于Document
并注入Sentence
,则无法将其绑定到this
中的Sentence
,因为它不会产生反应并被React禁止
if (newThis !== component && newThis !== null) {
monitorCodeUse('react_bind_warning', { component: componentName });
console.warn(
'bind(): React component methods may only be bound to the ' +
'component instance. See ' + componentName
);
}
请注意,已添加newThis !== null
。在尝试绑定道具功能时,实际上已经添加了这个来解决这个问题。
现在你可以写了
<Sentence value={sentenceData} onKeyDown={me.props.onKeyDown.bind(null,sentenceData} />
在文档上你有一个听众:
onKeyDown: function (sentenceData) { }
这非常好:)
请注意,还有另一种方法可以解决这个问题,这可能会更有效:
var Sentence = React.createClass({
onKeyDown: function(e) {
this.props.onKeyDown(this.props.value)
},
render: function () {
return (<span
contenteditable="true"
onKeyDown={this.props.onKeyDown}>
{this.props.value}
</span>);
}
});
您只需创建一个具有此通常绑定的唯一函数的类,而不是绑定函数。在这种情况下,我认为它会创建更多的耦合,因为您实际上并没有从Sentence
组件外部控制回调的行为。
答案 1 :(得分:0)
你对自己的错误问题有所了解。
无论您指向的相关onKeyDown处理程序应该在哪里(即句子或段落),您都需要处理数据更改然后调用:
this.setState({stateName: newdata})
这将导致使用新数据重新呈现组件的反应。
举个好例子,请看facebook's tutorial for a comment widget。
您可以通过添加新注释来查看表单如何处理数据更改,然后调用setState()以使用其他注释重新呈现。 React处理其他所有事情。
在您的示例中,如果您更改段落中的某些内容,则在您完成所需的所有工作后,段落应使用新的句子数据调用setState,然后做出反应将处理其余内容。