"小和山的菜鳥們",爲前端開發者提供技術相關資訊以及系列基礎文章。爲更好的用戶體驗,請您移至咱們官網小和山的菜鳥們 ( xhs-rookies.com/ ) 進行學習,及時獲取最新文章。html
"Code tailor" ,若是您對咱們文章感興趣、或是想提一些建議,微信關注 「小和山的菜鳥們」 公衆號,與咱們取的聯繫,您也能夠在微信上觀看咱們的文章。每個建議或是贊同都是對咱們極大的鼓勵!前端
react
的核心思想就是,將一個頁面拆成一堆獨立的,可複用的組件,而且用自上而下的單向數據流的形式將這些組件串聯起來。但若是你在大型的工做項目中用 react
,你會發現你的項目中實際上不少 react
組件冗長且難以複用。特別是那些 class
的組件,它們自己包含了 state
,很難進行復用。node
官方推薦解決方案react
prop
來傳遞須要動態渲染的 nodes
或組件.以下面的代碼能夠看到咱們的Provider
組件包含了全部跟狀態相關的代碼,而 MyComponent
組件則能夠是一個單純的展現型組件,這樣一來Provider
就能夠單獨複用了import MyComponent from 'components/myComponent'
class Provider extends React.Component {
constructor(props) {
super(props)
this.state = { target: 'MyComponent' }
}
render() {
return <div>{this.props.render(this.state)}</div>
}
}
<Provider render={(data) => <MyComponent target={data.target} />} />
複製代碼
這個模式叫 Render-Props
.web
固然通常狀況下,都會被寫成下面這樣的方式:ajax
<Provider>{(data) => <Cat target={data.target} />}</Provider>
複製代碼
withUser
函數就是一個高階組件,它返回了一個新的組件,這個組件具備了它提供的獲取用戶信息的功能。const withUser = (WrappedComponent) => {
const user = localStorage.getItem('user')
return (props) => <WrappedComponent user={user} {...props} />
}
const UserPage = (props) => (
<div class="user-page"> <p>I'm the user, {props.user}!</p> </div>
)
export default withUser(UserPage)
複製代碼
以上這兩種模式看上去都挺不錯的,不少庫也運用了這樣的模式,就像咱們經常使用的 React-router
庫。可是這兩種模式,會增長代碼的層級關係。爲了表現的明顯,能夠安裝打開 React Devtools 看看代碼的組件嵌套,會發現嵌套次數太多太多。chrome
而若是咱們使用 hooks
,那就會簡潔不少,沒有多餘的層級嵌套。把各類想要的功能寫成一個一個可複用的自定義 hook
,當你的組件想用什麼功能時,直接在組件裏調用這個 hook
便可。瀏覽器
咱們一般但願一個函數只作一件事情,但咱們的生命週期鉤子函數裏一般同時作了不少事情。好比咱們須要在 componentDidMount
中發起請求獲取數據,綁定一些事件監聽等等。同時,有時候咱們還須要在 componentDidUpdate
作一遍一樣的事情。緩存
當咱們的這個頁面或者這個組件,變得複雜的時候,裏面的內容就會變多,邏輯的清晰度就會降低。微信
父組件給子組件傳遞函數時, 必須綁定 this
react
中的組件四種綁定 this
方法的區別class App extends React.Component<any, any> {
handleClick2
constructor(props) {
super(props)
this.state = {
num: 1,
title: ' react study',
}
this.handleClick2 = this.handleClick1.bind(this)
}
handleClick1() {
this.setState({
num: this.state.num + 1,
})
}
handleClick3 = () => {
this.setState({
num: this.state.num + 1,
})
}
render() {
return (
<div> <h2>Ann, {this.state.num}</h2> <button onClick={this.handleClick2}>btn1</button> <button onClick={this.handleClick1.bind(this)}>btn2</button> <button onClick={() => this.handleClick1()}>btn3</button> <button onClick={this.handleClick3}>btn4</button> </div>
)
}
}
複製代碼
this
,那麼每次父組件刷新的時候,若是傳遞給子組件其餘的 props
值不變,那麼子組件就不會刷新render()
函數裏面綁定 this
:由於 bind
函數會返回一個新的函數,因此每次父組件刷新時,都會從新生成一個函數,即便父組件傳遞給子組件其餘的 props
值不變,子組件每次都會刷新;()=>{}
箭頭函數:父組件刷新的時候,即便兩個箭頭函數的函數體是同樣的,都會生成一個新的箭頭函數,因此子組件每次都會刷新;綜上所述,若是不注意的話,很容易寫成第三種寫法,致使性能上有所損耗
能優化類組件存在問題
能在無需修改組件結構的狀況下複用狀態邏輯(**自定義 Hooks **)
能將組件中相互關聯的部分拆分紅更小的函數(好比設置訂閱或請求數據)
反作用的關注點分離:反作用指那些沒有發生在數據向視圖轉換過程當中的邏輯,如 ajax
請求、訪問原生dom
元素、本地持久化緩存、綁定/解綁事件、添加訂閱、設置定時器、記錄日誌等。以往這些反作用都是寫在類組件生命週期函數中的。而 useEffect
在所有渲染完畢後纔會執行,useLayoutEffect
會在瀏覽器 layout
以後,painting
以前執行。
如今,咱們對 hooks
已經有了一個大概的瞭解。
那麼以後就開始咱們的基礎 hooks
教程了。
在 hooks
系列中,咱們主要介紹四個項目中經常使用的鉤子:useState、useEffect、useRefs、useCallback.
若是大家想要了解一些其餘鉤子函數(useContext 、useReducer 、 useMemo 、 useImperativeMethods 、useMutationEffect、 useLayoutEffect),能夠去官網查看。
在下節中,咱們將爲你們介紹 useState
,敬請期待!