一、事件处理函数的使用
1.1 绑定事件处理函数
1.2 使用
<HelloWorld onClick={this.handleClick}/>
大括号中指定的是this对象即当前组件引用的点击事件处理函数。注意这里不需要圆括号(this.handleClick()),如果用圆括号,则是执行函数,并将函数返回作为圆括号的运行结果赋值给onClick属性。
如果我需要给事件处理函数传递参数怎么办?
1)因为使用圆括号传入参数,就会直接调用这个函数,并将返回值作为表达式结果,因此可以利用闭包实现。
class SignupForm extends React.Component{
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSelect = this.handleSelect.bind(this);
this.state = {
name:'',
password:'',
gender:'0'
};
}
handleChange(type){
var that=this;
return function(event){
var tempObj={};
tempObj[type]=event.target.value;
that.setState(tempObj);
}
}
handleSelect(event){
this.setState({gender:event.target.value});
}
render(){
console.log(this.state);
return (
<div>
<label>name:
<input type="text" onChange={this.handleChange('name')}/>
</label><br/><br/>
<label>password:
<input type="password" onChange={this.handleChange('password')}/>
</label><br/><br/>
</div>
)
}
}
ReactDOM.render(<SignupForm/>,document.body);
2)利用bind函数的特性,传入第一个参数是作用域,第二个参数就是默认参数了
class SignupForm extends React.Component{ constructor(props){
super(props); this.state = { name:'', password:'', gender:'0' } } handleChange(type,event){ var tempObj={}; tempObj[type]=event.target.value; this.setState(tempObj); } handleSelect(event){ this.setState({gender:event.target.value}); } render(){ console.log(this.state); return ( <div> <label>name: <input type="text" onChange={this.handleChange.bind(this,'name')}/> </label><br/><br/> <label>password: <input type="password" onChange={this.handleChange.bind(this,'password')}/> </label><br/><br/> </div> ) } } ReactDOM.render(<SignupForm/>,document.body);
使用箭头函数
// 不需要传入参数时 class APP extends React.Component{ render(){ return <List onClick={this.handleClick}/> } } // List组件点击事件时执行了this.props.onClick没有参数 // 说明传给他的函数不接受参数 class List extends React.Component{ render(){ return <p id="para" onClick={this.props.onClick}>abc</p> } } // 传入参数 class APP extends React.Component{ render(){ return <List onClick={index => this.handleClick(index)} /> } } // 利用箭头函数特性 // List组件点击时调用传入的函数this.props.onClick,这个函数有入参 // 因此props的onClick函数有入参,即APP中的onClick函数必须有入参 class List extends React.Component{ render(){ return <p id="para" onClick={(e) => this.props.onClick(id)}>abc</p> } } // 或者使用闭包 class List extends React.Component{ handleClick(id){ var that=this; return function(){ that.props.onClick(id); } } render(){ return <p id="para" onClick={this.handleClick(id)}>abc</p> } } // 或者 class List extends React.Component{ handleClick(id){ return function(){ this.props.onClick(id); } } render(){ return <p id="para" onClick={this.handleClick(id).bind(this)}>abc</p> } } // 因为子组件执行this.props.func时其实是在执行父组件的引用 class APP extends React.Component{ constructors(props){ super(props); this.handleClick=this.handleClick.bind(this); } handleClick(id){ // do something... } render(){ return <List onClick={this.handleClick}/> } } // 这里传给List组件的onClick其实就是this.handleClick // 因此List获得的this.props.onClick就是this.handleClick // 所以不需要再写参数
二、组件之间的协同
2.1 父子嵌套
父组件向子组件传递消息使用属性传递,子组件向父组件传递消息就要使用委托。
<script type="text/babel"> class GenderSelect extends React.Component{ render(){ return <select onChange={this.props.handleSelect}> // 子组件触发父组件的函数,使得父组件的事件函数调用 <option value="0">男</option> <option value="1">女</option> </select> } } class SignupForm extends React.Component{ constructor(props){
super(props); this.state = { name:'', password:'', gender:'0' };
this.handleChange = this.handleChange.bind(this);
this.handleSelect = this.handleSelect.bind(this); } handleChange(type){ var that=this; return function(event){ var tempObj={}; tempObj[type]=event.target.value; that.setState(tempObj); } } handleSelect(event){ this.setState({gender:event.target.value}); } render(){ console.log(this.state); return ( <div> <label>name: <input type="text" onChange={this.handleChange('name')}/> </label><br/><br/> <label>password: <input type="password" onChange={this.handleChange('password')}/> </label><br/><br/> <label>gender: <GenderSelect handleSelect={this.handleSelect}/> // 父组件利用属性传递给子组件事件名称 </label> </div> ) } } ReactDOM.render(<SignupForm/>,document.body); </script>
2.2 使用Mixin
将组件的一些共同处理部分提取出来,在组件中通过mixins传入Mixin
<script type="text/babel"> var BindingMixin={ // Mixin 抽取出来的部分 handleChange:function(type,event){ var tempObj={}; tempObj[type]=event.target.value; this.setState(tempObj); } }; var Comment=React.createClass({ mixins:[BindingMixin], // 传入数组 getInitialState:function(){ return { text:'enter', comment:'something', selectText:'male' } }, render:function(){ return ( <div> <input type="text" value={this.state.text} onChange={this.handleChange.bind(this,"text")}/> <p>the input is {this.state.text}</p> <textarea value={this.state.comment} onChange={this.handleChange.bind(this,"comment")}></textarea> <p>the textarea is {this.state.comment}</p> <select onChange={this.handleChange.bind(this,"selectText")}> <option value="male">男</option> <option value="female">女</option> </select> <p>the select is {this.state.selectText}</p> </div> ) } }); ReactDOM.render(<Comment/>,document.getElementById("example")); </script>
三、事件处理函数复用
3.1 bind复用
详见1.2
3.2 name复用
class SignupForm extends React.Component{ constructor(props){
super(props); this.state = { name:'', password:'', gender:'0' };
this.handleChange = this.handleChange.bind(this);
this.handleSelect = this.handleSelect.bind(this); }
// 给组件添加name属性,利用event.target.name属性来判断不同的组件,从而达到复用的目的 handleChange(event){ var tempObj={}; tempObj[event.target.name]=event.target.name=="checkbox"?event.target.checked:event.target.value; // checkbox读取的是checked属性,input读取的是value this.setState(tempObj); } handleSelect(event){ this.setState({gender:event.target.value}); } render(){ console.log(this.state); return ( <div> <label>name: <input type="text" name="text" onChange={this.handleChange}/> </label><br/><br/> <label>password: <input type="password" name="password" onChange={this.handleChange}/> </label><br/><br/> </div> ) } } ReactDOM.render(<SignupForm/>,document.body);