在 React 中事件的綁定是直接寫在 JSX 元件上的,並不需要透過 addEventListener 的方式進行監聽,那在寫法上:
小駝峰(camelCase)
的形式,事實上 React 已經有事先封裝好一些事件類型像是: onClick, onFocus, onMouseMove(可以參考w3c的規範)onclick="handleClick()"
,如今使用onClick={this.handleClick}
)on*EventType
事件類型只能作用在原生的 HTML 標籤上,不能作用在自定義的元件上event.preventDefault()
當給 DOM 綁定事件處理函數時,函數會自動傳入一個 event,這個 event 紀錄了當前事件的屬性和方法,在 React 中,雖然 event 不是瀏覽器提供的,但是由 React 將原生瀏覽器的 event 進行封裝,對外提供一個 API,這裡就無須考慮瀏覽器的兼容性,與原生瀏覽器處理事件方法一樣(像是event.preventDefault(), event.stopPropatation),以下為例子:
<a href="#" onClick={this.handleLinkClick}>連結</a>
handleLinkClick(event) {
event.preventDefault();
console.log(event);
}
這裏的 event 將回傳:
下方的例子在元件建置的時候,雖然沒有寫 constructor 但預設會自動建立並且將 this
綁定進元件裡,所以 在render 後會顯示 handler 的 this 指向 APP
,而在在點擊h1
時,會顯示 點擊了
以及 handler 的 this 指向 undefined
,原因是因為它並沒有將 this 傳給 handleWordClick 這個 function 導致 undefined(詳細原因可以參考 DAY 8)。
import React from 'react';
export default class App extends React.Component {
handleWordClick() {
console.log('點擊了');
console.log('handler 的 this 指向', this);
}
render() {
console.log('handler 的 this 指向', this);
return (
<div>
<h1 onClick={this.handleWordClick}>點擊我</h1>
</div>
)
}
}
constructor(props) {
super(props);
this.handleWordClick = this.handleWordClick.bind(this);
}
<h1 onClick={this.handleWordClick.bind(this)}>點擊我</h1>
ps. 但是還是比較建議在 constuctor 進行 this 環境的綁定,而非在 render 時通過 bind
方法綁定,因為那會在每次元件渲染的時候都創建一個新的函數,而影響到性能,相反的 contructor 只會執行一次。
在操作列表中,有時候為了實現某些操作我們需要額外向事件函數傳遞其他的參數(像是索引),要選取哪一行的ID,那可以透過下面兩種方式向事件函數傳遞參數。
<button onClick={this.handleSelectRow.bind(this.id)}>選取</button>
// 等同於
<button onClick={(e) => this.handleSelectRow(id, e)}>選取</button>
以下例子則是以刪除 list 內部 item,程式如下:
檔案位置,src/listitem.js
import React, { Fragment, Component } from 'react';
export default class ListItem extends Component {
constructor(props) {
super(props);
const { list } = this.props;
this.state = {
list,
}
}
handleDelete(index, e) {
console.log(e);
// 這裏用拷貝的方式,不建議直接去更動 state
const list = [...this.state.list];
list.splice(index, 1);
this.setState(() => ({list}));
}
render() {
const { list } = this.state;
return (
<Fragment>
<ul>
{list.map((item, index) =>
<li
onClick={(event) => this.handleDelete(index, event)}
key={index}
>
{item}
</li>
)}
</ul>
</Fragment>
)
}
}
檔案位置,src/index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import ListItem from './listitem';
const listData = ['Hello', 'World', 'Test', 'Case'];
ReactDOM.render(
<ListItem list={listData} />,
document.getElementById('root')
);