事件繫結
React 元素的事件處理和 DOM元素的很相似。但是有一點語法上的不同:
- React事件繫結屬性的命名採用駝峰式寫法,而不是小寫。
- 如果採用 JSX 的語法你需要傳入一個函式作為事件處理函式,而不是一個字串(DOM元素的寫法)
- 阻止事件預設行為只能呼叫e.preventDefault; 而DOM事件還可以使用 return false
例如:
傳統dom事件
<button onclick="activateLasers()">
Activate Lasers
</button>
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
複製程式碼
React事件
<button onClick={activateLasers}>
Activate Lasers
</button>
function ActionLink() { function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}複製程式碼
this指向
JSX 中事件繫結的回撥函式中,this並不會指向React元件例項。儘管ES6規範中,class類的方法中,this預設指向類的例項,單如果單獨使用該方法,this會指向函式呼叫的上下文。jsx中事件繫結函式,就是單獨使用,this並不會指向組建的例項。如何繫結this到元件例項,有如下幾種方法:
1. 使用箭頭函式,直接在React元素中採用箭頭函式定義事件的處理函式,如下:
<button onClick={(e) => {console.log(this.state.number)}}> 點選 </button>複製程式碼
因為箭頭函式中this指向的是函式定義是的物件,故保證this總是指向當前元件的例項物件。
但是如果事件處理邏輯較多,這樣直接在元素上寫,造成程式碼可讀性差,故一般把邏輯封裝成元件的一個方法,然後在箭頭函式中呼叫這個方法。
handleClick(event) {
this.setState({})
}
render(){
return <button onClick={(e) => {this.handleClick(event)}}> 點選 </button>}複製程式碼
缺點: 直接在render方法中為元素事件定義事件處理函式,每次render呼叫,都會重新建立一個新的事件處理函式。
2. 使用元件的方法,直接將元件方法賦值給元素的事件屬性,同時在類的建構函式中,將這個方法的this繫結到當前物件,如:
class Header extends React.componet {
constructor (props) {
super (props)
this.handleClick = this.handleClick.bind(this)
}
handleClick() { }
render() {
return <button onClick={this.handleClick}> 點選 </button>
}
複製程式碼
3. 還是使用元件的方法,不過是在給元素的時間屬性賦值的時候,同時為時間處理函式繫結this,如果需要向處理函式傳遞額外的引數,這種方式很方便
handleClick(number, event) {
}
render() {
return <button onClick={this.handleClick.bind(this,3)}> 點選 </button>
}
複製程式碼
4. ES7的屬性初始化語法,自動為class中定義的方法繫結this,如:
handleClick = (event) => {
}
render() {
return <button onClick={this.handleClick}> 點選 </button>
} 複製程式碼
參考阮一峰es6書中,19.14.1小節,應該也算是Class的例項屬性新的寫法
class Myclass {
myprop = 42;
consturctor() {
this.name = "killer"
}
}複製程式碼
myprop 和 name 都是例項的屬性,只是寫法不一樣
5. ES新提案語法--雙冒號語法,不能帶引數
bind5(){
console.log('bind5', this)
}
render() {
return (
<div>
<button onClick={::this.bind5}></button>
</div>
)
}複製程式碼
傳參
通常我們會為事件處理程式傳遞額外的引數。例如,若是 id
是你要刪除那一行的 id,以下兩種方式都可以向事件處理程式傳遞引數:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>複製程式碼
引數 e
作為 React 事件物件將會被作為第二個引數進行傳遞。通過箭頭函式的方式,事件物件必須顯式的進行傳遞,但是通過 bind
的方式,事件物件以及更多的引數將會被隱式的進行傳遞。
值得注意的是,通過 bind
方式向監聽函式傳參,在類元件中定義的監聽函式,事件物件 e
要排在所傳遞引數的後面,例如:
class Popper extends React.Component{
constructor(){
super();
this.state = {name:'Hello world!'};
}
preventPop(name, e){ //事件物件e要放在最後
e.preventDefault();
alert(name);
}
render(){
return (
<div>
<p>hello</p>
{/* Pass params via bind() method. */}
<a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
</div>
);
}
}複製程式碼
參考 : https://react.docschina.org/docs/handling-events.html