昨天有說到因為篇幅的問題,接下來的官方文件學習之路腳步會有所加快,廢話不多說 馬上進入正題。
有接觸過Jquery或原生JS的同學們對於事件處理一定非常熟悉,所以關於原生的事件我這裡就簡單敘述。
原生的事件邏輯基本上就是:query selector 選到目標Dom → 掛載事件監聽 → 寫事件處觸發要做什麼事情。
就是一套基本的萬用邏輯來處理畫面跟使用者的互動
另外有一種寫法可以不用去選擇dom掛監聽,作法就是直接在html element上面加 事件監聽。
React主要都是採用後者的方法,當element render到畫面上時,已經把監聽掛好了
React跟html事件監聽不同的地方是: html 會把function寫成字串 例如:
onClick="goHome()"
而React會這樣寫:
onClick={goHome} //注意 這裡不用括號
如果這裡加上括號會怎樣? A:會直接執行,因為在Js的事件中 我們需要去呼叫一個function就是直接寫function Name + 括號
所以當程式碼執行到goHome的時候 會直接執行
那如果我們想要在這個地方加入parameter給goHome這個function怎麼辦?
其實解法很簡單,我們只要在goHome外面再包一層function 就可以了
ocClick={ () => { goHome("Taipei City") }}
另外,如果要使用 "避免html預設功能"
就需要使用e.preventDefault 不能夠使用return false這個古老的寫法XD
接下來我這裡想針對這個範例做比較深入的理解:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 為了讓 `this` 能在 callback 中被使用,這裡的綁定是必要的:
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
【範例小補充】
在看這個範例之前我想先講一下關於bind這個東西,bind在中文就是綁定的意思
接下來我們直接看實例:
let staff = {
name: "bennett",
age: 23,
education: "university"
}
function bennett(){
console.log(this.name);
}
bennett();
這時候會出現undefined,因為這個時候對於bennett 這個function 來說 它的this指的是window object
所以我們要把指定物件綁定到這個function身上,改成如下
let staff = {
name: "bennett",
age: 23,
education: "university"
}
function bennett(){
console.log(this.name);
}
let bennettName = bennett.bind(staff);
bennettName(); //bennett
接下來我們正式解讀這個範例
首先我們先看construct,起手式的prop就不用看了。
繼續往下看 可以看到創立了一個新的state ,內容包含isToggleOn是true
然後再往下可以看到這裡把this綁定到handleClick這個function之中
所以handleClick如果使用this,就會拿到construct的this object
然後
看到Component render畫面的地方做了一個三元運算子的判斷,如果isToggleOn是true就出現on反之off
接著可以看到onclick 去呼叫handleClick的function
這個function 裡面去setState isToggleOn的數值(這裡為了確保每次的state都是最新,有用到arrow function + 兩個參數 的方式,忘記的朋友們可以去昨天的文章複習一下)
---React 事件結束---
如果是平常就在進行網頁開發的工程師,一定都會遇到某些條件才需要顯示/ 不同條件下要顯示不同內容的這個問題;在React之中可以利用建立不同的Component並根據state的狀態來判斷要render誰
官方範例,這個是根據props的資訊來判斷要回傳哪個component
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
// Try changing to isLoggedIn={true}:
root.render(<Greeting isLoggedIn={false} />);
當然也可以利用過去所學到的其他技巧來判斷
class LoginControl extends React.Component {
//這裡是一個component
constructor(props) {
super(props);
/*要把this 物件分享,所以這裡要綁定*/
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
//這裡是function
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
//這裡是function
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />; //向下資料流實作範例
} else {
button = <LoginButton onClick={this.handleLoginClick} />; //向下資料流實作範例
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
function UserGreeting(props) {
//這裡是一個component
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
//這裡是一個component
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
//這裡是一個component
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
function LoginButton(props) {
//這裡是一個component , 這裡會收到上面丟下來function
return (
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props) {
//這裡是一個component , 這裡會收到上面丟下來function
return (
<button onClick={props.onClick}>
Logout
</button>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<LoginControl />);
因為這裡的code比較長,比較容易混淆 所以我自己做了一些簡單的解析:
畫面邏輯:
1. 一開始將LoginControl render到root,所以可以到LoginControl看看。
2. LoginControl是一個component 本身的state 預設是false
3. 接著到LoginControl render畫面的地方,可以看到針對state 的true false 會丟到不同的component拿按鈕
4. 這裡注意LoginControl有使用到向下資料流,把如果被點擊需要觸發的function當成prop丟給LoginButton或LogoutButton
5. LoginButton或LogoutButton各自回傳button回去給LoginControl
6. 這時候LoginControl 已經取得了關於button的element
7. 繼續往下看 LoginControl return 了一個Greeting的component並把false當成props丟下去
8. Greeting收到false之後回傳了 GuestGreeting這個component回去
點擊行為發生時:
1. LoginButton 或者 LogoutButton觸發onclick,去找相對應的function執行(假設觸發handleLoginClick)
2. 這時候handleLoginClick function 把state改成true,因為state的更新,所以畫面會重新render
3. isLoggedIn變成了true,所以buttom變數會到LogoutButton Component來取得對應的button資料(這裡一樣向下把對應的function當成props丟出)
4. 這時候LoginControl 已經取得了關於button的element
5. 繼續往下看 LoginControl return 了一個Greeting的component並把true當成props丟下去
6. Greeting收到true之後回傳了 UserGreeting這個component回去
官方有另外提供兩種比較簡短的if、else寫法,有興趣的話可以到文件看看
另外還有透過return Null的方式來防止component Render 礙於篇幅,這裡就不做範例解析了~
明天會繼續介紹react的其他特性,不過會挑重點講,因為當初幫react設定的篇幅就是10篇