2017-07-18 40 views
1

我有這個課程。在所有函數中,除了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; 
 
    } 
 
    }

地圖類重複的解決方案:

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

我不明白這是爲什麼總是空。你可以幫我嗎? 謝謝

回答

2

代碼中有很多問題。首先,this作用域在函數beacuse中不可用,但您沒有正確綁定它。您可以使用構造函數將this綁定到該函數。這種綁定只會發生一次,這將避免每次呈現inline綁定的重複綁定。其次,(只是爲了更好的實踐)儘量避免使用危險的SetInnerHTML,因爲React不會意識到這些DOM節點,所以無法通過差異提供更好的性能。並且避免在渲染中聲明函數,每次調用渲染時都會聲明它們。

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

1

你在上面的代碼片段中有幾個問題。

首先,你喜歡寫東西onInput={this.emitChange},然後this上下文將丟失 - 所以使用bind操作或使用新的雙冒號語法(在你的通天預設的支持它,像https://gist.github.com/islahul/73f99302a721a714c002)。

其次,底層HTML元素可以通過ref操作找到。使用類似<div ref={elm => (this.componentRootDOM = elm)}></div>的東西,然後調用this.componentRootDOM獲取React生命週期功能。

2

你必須將它綁定到將在渲染函數中觸發的函數。最好的方法是爲組件添加一個構造函數(最佳做法是將其添加爲第一個函數)。

class Idea extends React.Component { 
    constructor(props) { 
    super(props); 
    this.emitChange = this.emitChange.bind(this); 
    } 
    ... 
} 
1

而不是使用綁定方法,作爲一種替代你也可以使用property initializer syntax聲明emitChange,基本上變成這樣:

_emitChange =() => { 
    var html = ReactDOM.findDOMNode(this).innerHTML; 
    if (this.props.onChange && html !== this.lastHtml) { 

     this.props.onChange({ 
      target: { 
       value: html 
      } 
     }); 
    } 
    this.lastHtml = html; 
}; 

在這種情況下,您只有1個方法來綁定任何一種方法都可以,但是在有更多方法的情況下,屬性初始值設定器語法可能會爲構建器節省一些臃腫