今天(指兩天)繼續學習 React。html
//普通 html: <button onclick="printMe()"></button> // JSX <button onClick={printMe()}></button>複製代碼
能夠看到:①onclick成爲了onClick。②函數不能用引號react
在 React 中,一般是在元素初始化的時候添加監聽器,而不是用 addEventListener,由於操做的基本都是 React 元素而不是 DOM 元素。數組
// function 組件 function Button(props){ function handleClick(e){ e.target.style.color = "red"; } return (<button onClick={handleClick}>A button</button>); }複製代碼
class 組件須要注意 this 的指向,由於在 onClick={handleClick} 中,handleClick 是回調函數,回調函數的 this 是指向 window 的,這是 JS 的默認行爲。所以須要在構造函數中對 handleClick 進行綁定處理(這沒有問題,由於原型方法比構造函數更早)。瀏覽器
// class 組件 class Button extends React.Component { constructor(props){ super(props); this.handleClick = this.handleClick.bind(this); // 給 handleClick 綁定 this // 由於該函數以後會被用做回調函數 } handleClick() { console.log(this); } render() { return ( <button onClick={ this.handleClick }> // 回調函數 A button </button> ); } }複製代碼
給事件處理函數添加參數有兩種方法,箭頭函數或者 bind。ide
<button onClick={ (e) => this.handleClick(id, e, oid) }>A button</button> <button onClick={ this.handleClick.bind(this, id, oid) }>A button</button>複製代碼
區別在於事件對象的傳入(皆以上面代碼的參數傳入順序爲例):函數
條件渲染並非新的語法,只是一種使用方式。好比說建立三個組件,UserGreeting, GuestGreeting, Greeting。其中 Greeting 根據登陸狀態返回剩餘兩個組件中的一個。學習
把一些元素存進變量,以後再用大括號組合進其餘元素,因爲變量能夠根據條件改變,渲染也會改變,以下圖(LoginButton 和 LogoutButton 事先已建立)。this
上面在大括號裏嵌入存儲了元素的變量。其實因爲大括號裏能夠嵌入表達式,還有不少種方式來寫。好比與運算符 &&。3d
return ( { isLogin && <LogoutButton />} );複製代碼
isLogin 爲 false 的時候,後面的部分不會運行。老技巧了。component
沒什麼好說的。上面的例子能夠改寫成這樣。
簡化了許多。
若是在 render 裏返回 null,則組件不會被渲染。
可是組件的生命週期不受影響會照常進行。
表達式能夠解析列表。
若是運行上述第二個代碼,控制檯會有報錯提示每個列表元素必須有 key 屬性,以下:
key 只有放在數組上下文附近纔有意義。這個很差描述,具體見文章。
key 只能被 React 自身使用,無法訪問。若是想要使用 key 的值,只能在傳值給 key 的時候,傳給一個別的屬性,再去訪問那個屬性。
受控組件指的是受代碼控制而不是用戶控制的組件。
一個普通的表單元素,會受到用戶控制,每當用戶輸入的時候,表單的 value 就會更改。
要想接受用戶的輸入,就要使用組件的 state,例如:
爲了控制填入的值,須要使用 onChange,每次輸入框用戶改變值的時候,都會更新 state:
e 事件被傳入是能夠預測的,由於 onChange 是 React 的語法,其背後仍是 js 的 onchange 函數,以上寫法其實至關於:
const btn = document.querySelector("input[type='input']"); btn.onchange = (e) => {};複製代碼
事件函數原本就會有 e 傳入,很合理。
原始的 textarea 的值並非 value 屬性而是標籤內部內容,可是 React 將其改成 value 屬性,所以用法徹底和 input 同樣。
寫法以下:須要注意的幾點以下:
文件輸入只能被用戶控制,只能爲非受控組件。
這裏指的不是 multiple select 那種。而是處理多個輸入標籤,如:。
處理方式是加上 name 屬性,handleChange 的時候根據 name 判斷更改哪一個框的值。
通常來講,若是設置了 value 的值,則輸入框會變成只讀。但有時候設置了 value(而且沒有設置 handleChange),但仍然能夠編輯,那說明 value 的值爲 null 和 undefined。(好比說使用某個變量的值,而後這個變量由於某種狀況變成了 undefined 或者 null。)
從上面能夠看出,每一種輸入類型都要爲之寫專門的輸入處理,這很麻煩。有時候只須要簡單的輸入而後提交,不須要作複雜的判斷(好比實時判斷),只須要正在提交的時候是正確的值便可。那麼此時能夠用非受控組件。
因爲非受控組件須要使用 ref,放在以後學習。不過有一張表顯示二者之間的區別,助你決定使用哪一個:
官方文檔推薦了 Formik,用於輕鬆管理複雜的表單驗證。
狀態提高用於多個組件共享相同的變化數據。
這裏仍是參考文檔來看比較好。
一些坑和心得:
props.children 是一個特殊命名的屬性:這裏使用組件的方式再也不是 <Panel />,而是使用開放和閉合標籤包裹了一段 html 內容。這段內容將會做爲 props.children 傳給子組件。
props.children 是特殊屬性,傳的是整個 innerHTML。若是想傳一些自定義的元素的話。能夠直接以相似:<MyComponent myDefined={<h1>this is a title</h1>}> 的方式傳遞,props 並不對值的類型有要求。JSX 語法自己也只是元素。
能夠經過以上語法 「組合」 成新的組件。