iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
0
Modern Web

為期 30 天的 react 大冒險系列 第 15

react 大冒險-react 事件處理-day 14

  • 分享至 

  • xImage
  •  

上篇提及的 state 跟 setState,這裡談談在 react 內的 event handling

Handling Events in js

一般 js 進行事件傳遞是這樣..

  • event attribute 皆為小寫(ex: onchange / onclick / onblur)
  • event 的值 在 html DOM 中為字串
  • 可用 return false 阻止瀏覽器 預設動作

在 html DOM 中

<button onclick="clickHandler()">Click</button>

js 內

function clickHandler (){
    console.log('clicked!');
}

或直接在 html 內寫匿名函式

<button onclick="function(){console.log('clicked!');}">Click</button>

當然也可以用 arrow function 取代

<button onclick="()=>{console.log('clicked!');}">Click</button>

Handling Events in react

多數 state 的變更因觸發事件而造成改變,在 react 中事件觸發跟 pure js 有幾點不同

  • event attribute 以 駝峰式(camelCase) 寫法來編寫 (ex:onClick , onChange , onBlur)
  • event 的值在 jsx 中是 function(直接用 functionName callback)
  • 不需 addEventListener 來監聽
  • preventDefault 阻止瀏覽器預設動作 且不可 return false
    傳入 evt,然後 evt.preventDefault()
function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

事件與綁定

在 js 中,class 上的 method 預設沒有被綁定,在還沒綁定的狀態下,如果 call this.functionName 的話,會產生 TypeError: Cannot read property 'setState' of undefined 的錯誤

要記得將 method 綁到 class 實體(也就是 this)上
在 react 中,有三種事件綁定方式

  1. arrow function 綁定
    好處是不需要寫任何 bind 跟 this
    缺點是每次重渲染都會產生一個新 function 當牽涉的 component 數量一多,可能造成效能上的影響,且綁定到多項 component 上要重複綁定

例子:

<button onClick = {
        () => {
            this.setState((state) => ({
                isDark: !state.isDark
            }));
        }
    } > click to toggle 
</button>
  1. 在 method 內 binding inline
    好處是語法明確,明顯知道 bind 在哪裡
    缺點一樣是每次重渲染都會產生一個新 function且綁定到多項 component 上要重複綁定

例子:

<button onClick = {this.toggleHandler.bind(this)}> 
    click to toggle 
</button>
  1. 建構子(constructor) 中將 method bind 到 class 實體上,this.functionName = this.functionName.bind(this)
    好處是語法明確,綁定一次就完成

例子:

constructor(props){
    super(props);
    // 略...
    this.toggleHandler = this.toggleHandler.bind(this);
}
// 略...
render(){
    return(
        <button onClick={this.toggleHandler}>toggle</button>
    )
}

最後,用一個 toggle state 進行底色亮暗切換的 component 作例子

class ToggleBtn extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			isDark: true,
		};
		this.toggleHandler = this.toggleHandler.bind(this); // 在 constructor 中進行 bind
	}
	toggleHandler() {
		this.setState((state) => ({ isDark: !state.isDark }));
	}
	render() {
		const dark = { backgroundColor: "#222" };
		const light = { backgroundColor: "#ffdd00" };
		const { isDark } = this.state;
		return (
			<div style={isDark ? dark : light}>
				<p style={isDark ? { color: "#fff" } : { color: "#222" }}>
					{isDark ? "dark mode" : "light mode"}
				</p>
				<button onClick={this.toggleHandler}>click to toggle</button>
			</div>
		);
	}
}

效果如下


上一篇
react 大冒險-關於setState-day 13
下一篇
react 大冒險-styling component-day 15
系列文
為期 30 天的 react 大冒險30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言