我有这门课。在所有函数中,除了Idea类中的render()之外,它等于null。 我试图从React.js: onChange event for contentEditable
重复解决方案
class Idea extends React.Component {
render() {
return (
<div id="root"
onInput={this.emitChange}
onBlur={this.emitChange}
contentEditable
dangerouslySetInnerHTML={{__html: this.props.html}}>
</div>
);
}
shouldComponentUpdate(nextProps) {
return nextProps.html !== ReactDOM.findDOMNode(this).innerHTML;
}
componentDidUpdate() {
if (this.props.html !== ReactDOM.findDOMNode(this).innerHTML) {
ReactDOM.findDOMNode(this).innerHTML = this.props.html;
}
}
emitChange() {
var html = ReactDOM.findDOMNode(this).innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({
target: {
value: html
}
});
}
this.lastHtml = html;
}
}
&#13;
地图类:
class Map extends React.Component {
render() {
var handleChange = function (event) {
this.setState({html: event.target.value});
}.bind(this);
return (
<div>
<Header/>
<div id="map">
{this.props.map.root && (
<Idea html={this.props.map.root.title} idea={this.props.map.root} onChange={handleChange}/>
)}
</div>
</div>
);
}
}
&#13;
我不明白为什么这总是空的。你能帮助我吗? 感谢
答案 0 :(得分:2)
您必须将此绑定到将在渲染功能中触发的函数。最好的方法是为组件添加构造函数(最佳做法是将其添加为第一个函数)。
class Idea extends React.Component {
constructor(props) {
super(props);
this.emitChange = this.emitChange.bind(this);
}
...
}
答案 1 :(得分:2)
您的代码中存在许多问题。首先,函数beacuse中没有this
范围,您没有正确绑定它。您可以使用构造函数将this
绑定到函数。这种绑定只会发生一次,这将避免重复绑定每个渲染内联绑定。
其次,(仅为了更好的练习)尽量避免使用dangerouslySetInnerHTML,因为React不会知道这些DOM节点,因此无法通过diffing提供更好的性能。并且避免在render中声明函数,这将在每次调用render时声明int。
class Idea extends React.Component {
constructor () {
super();
this.emitChange = (e) => this._emitChange(e);
}
render() {
return (
<div id="root"
onInput={this.emitChange}
onBlur={this.emitChange}
contentEditable>
{this.props.children}
</div>
);
}
shouldComponentUpdate(nextProps) {
return nextProps.html !== ReactDOM.findDOMNode(this).innerHTML;
}
componentDidUpdate() {
if (this.props.html !== ReactDOM.findDOMNode(this).innerHTML) {
ReactDOM.findDOMNode(this).innerHTML = this.props.html;
}
}
_emitChange() {
var html = ReactDOM.findDOMNode(this).innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({
target: {
value: html
}
});
}
this.lastHtml = html;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
class Map extends React.Component {
constructor () {
super();
this.handleChange = (e) => this._handleChange(e);
}
// i dont get why do you store the event in state, if you dont use it.
_handleChange = function (event) {
this.setState({html: event.target.value});
}
render() {
return (
<div>
<Header/>
<div id="map">
{this.props.map.root && (
<Idea idea={this.props.map.root} onChange={this.handleChange}>
{this.props.map.root.title}
</Idea>
)}
</div>
</div>
);
}
}
答案 2 :(得分:1)
您在上面的代码段中有几个问题。
首先,你写了类似this.authenticationFactory
的内容,然后onInput={this.emitChange}
上下文将丢失 - 所以使用this
操作或使用新的双冒号语法(在你的Babel预设集中支持它,比如https://gist.github.com/islahul/73f99302a721a714c002)。
其次,bind
操作可以找到基础HTML元素。使用ref
之类的内容,然后为React生命周期函数调用<div ref={elm => (this.componentRootDOM = elm)}></div>
。
答案 3 :(得分:1)
除了使用绑定方法之外,您还可以使用emitChange
声明property initializer syntax
,而不是使用绑定方法,基本上就是这样:
_emitChange = () => {
var html = ReactDOM.findDOMNode(this).innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({
target: {
value: html
}
});
}
this.lastHtml = html;
};
在这种情况下你只有一个方法来绑定任何一种方法都没问题,但是在你有更多方法的情况下,属性初始化器语法可能会在构造函数中保存一些膨胀