我对Facebook的React世界还很陌生。他们的文档似乎非常好,但是在某些方面我需要一点点澄清。这就是其中之一。
Src:http://tuts-javascript.appspot.com/reactjs-add-remove-table-row
var CompanyApp = React.createClass({ getInitialState: function() { return {companylist:this.props.companies}; }, handleNewRowSubmit: function( newcompany ) { this.setState( {companylist: this.state.companylist.concat([newcompany])} ); }, handleCompanyRemove: function( company ) { var index = -1; var clength = this.state.companylist.length; for( var i = 0; i < clength; i++ ) { if( this.state.companylist[i].cname === company.cname ) { index = i; break; } } this.state.companylist.splice( index, 1 ); this.setState( {companylist: this.state.companylist} ); }, render: function() { var tableStyle = {width: '100%'}; var leftTdStyle = {width: '50%',padding:'20px',verticalAlign: 'top'}; var rightTdStyle = {width: '50%',padding:'20px',verticalAlign: 'top'}; return ( <table style={tableStyle}> <tr> <td style={leftTdStyle}> <CompanyList clist={this.state.companylist} onCompanyRemove={this.handleCompanyRemove}/> </td> <td style={rightTdStyle}> <NewRow onRowSubmit={this.handleNewRowSubmit}/> </td> </tr> </table> ); } }); var CompanyList = React.createClass({ handleCompanyRemove: function(company){ this.props.onCompanyRemove( company ); }, render: function() { var companies = []; var that = this; // TODO: Needs to find out why that = this made it work; Was getting error that onCompanyDelete is not undefined this.props.clist.forEach(function(company) { companies.push(<Company company={company} onCompanyDelete={that.handleCompanyRemove} /> ); }); return ( <div> <h3>List of Companies</h3> <table className="table table-striped"> <thead><tr><th>Company Name</th><th>Employees</th><th>Head Office</th><th>Action</th></tr></thead> <tbody>{companies}</tbody> </table> </div> ); } }); var Company = React.createClass({ handleRemoveCompany: function() { this.props.onCompanyDelete( this.props.company ); return false; }, render: function() { return ( <tr> <td>{this.props.company.cname}</td> <td>{this.props.company.ecount}</td> <td>{this.props.company.hoffice}</td> <td><input type="button" className="btn btn-primary" value="Remove" onClick={this.handleRemoveCompany}/></td> </tr> ); } }); var NewRow = React.createClass({ handleSubmit: function() { var cname = this.refs.cname.getDOMNode().value; var ecount = this.refs.ecount.getDOMNode().value; var hoffice = this.refs.hoffice.getDOMNode().value; var newrow = {cname: cname, ecount: ecount, hoffice: hoffice }; this.props.onRowSubmit( newrow ); this.refs.cname.getDOMNode().value = ''; this.refs.ecount.getDOMNode().value = ''; this.refs.hoffice.getDOMNode().value = ''; return false; }, render: function() { var inputStyle = {padding:'12px'} return ( <div className="well"> <h3>Add A Company</h3> <form onSubmit={this.handleSubmit}> <div className="input-group input-group-lg" style={inputStyle}> <input type="text" className="form-control col-md-8" placeholder="Company Name" ref="cname"/> </div> <div className="input-group input-group-lg" style={inputStyle}> <input type="text" className="form-control col-md-8" placeholder="Employee Count" ref="ecount"/> </div> <div className="input-group input-group-lg" style={inputStyle}> <input type="text" className="form-control col-md-8" placeholder="Headoffice" ref="hoffice"/> </div> <div className="input-group input-group-lg" style={inputStyle}> <input type="submit" className="btn btn-primary" value="Add Company"/> </div> </form> </div> ); } }); var defCompanies = [{cname:"Infosys Technologies",ecount:150000,hoffice:"Bangalore"},{cname:"TCS",ecount:140000,hoffice:"Mumbai"}]; React.renderComponent( <CompanyApp companies={defCompanies}/>, document.getElementById( "companyApp" ) );
这是关于ReactJS如何工作的很好的基本解释。感谢作者。
但是这个评论
var that = this; // TODO:需要找出原因,这使它起作用;正在收到错误,指出onCompanyDelete不是未定义的
为什么有必要?这是正确的方法吗?如果没有,那是什么?
提前致谢。
对于ReactJS,没有“ this”这个谜。
这只是标准范围界定问题的一种情况,这些问题随着JavaScript中的回调而出现。
当您处于React this组件中时,就像其他任何JavaScript“类”一样,基本组件上的所有方法都将以当前组件为范围。
this
在您的代码段中,您有一个render方法,该方法是基本组件上的函数,因此this与组件本身相同。但是,在该render方法中,您要使用调用回调this.props.clist.forEach,方法中的任何函数回调render都需要绑定到正确的this作用域,或者可以这样做var that = this(尽管这是一种反模式,因此不建议使用)。
render
this.props.clist.forEach
var that = this
例如,您的代码片段的简化版本:
var MyComponent = React.createClass({ handleCompanyRemove: function(e) { // ... }, render: function() { // this === MyComponent within this scope this.props.someArray.forEach(function(item) { // this !== MyComponent, therefore this.handleCompanyRemove cannot // be called! }) } })
从上面的注释中可以看出,如果没有在外部定义变量或正确绑定函数,.forEach则无法this直接使用for的回调。
.forEach
解决此问题的其他选项是:
*将回调函数 *绑定 到正确的此范围。例:
this.props.someArray.forEach(function(item) { // this === MyComponent within this scope too now! // so you can call this.handleCompanyRemove with no problem }.bind(this))
如果使用的是Babel / ES6,则可以使用 Fat Arrow 函数语法,该语法可确保this作用域继续从父作用域继续进行回调。例:
this.props.someArray.forEach((item) => { // this === MyComponent within this scope too now! // so you can call this.handleCompanyRemove with no problem })