一、react是什么?
react是一個js框架,可以用它來編寫html頁面,使用react后我們可以完全拋棄html(只需要一個主index文件),而用純js來編寫頁面;
二、為什么要使用react
和直接用html編寫頁面相比,使用react有以下幾點好處:
1. 便於代碼的復用
用html編寫頁面時,如果多個頁面擁有基本相同的模塊,那么需要把相關模塊在各個html文件中全部復制一遍。而使用react我們只需要把這些模塊寫成組件,在各個頁面中調用這個組件即可;
2. 提高渲染效率
當信息發生改變時,需要重新渲染頁面,如果用html編寫,我們需要花很多精力考慮架構問題,保證渲染效率;而react把這些問題封裝了起來,編寫高性能頁面會變得特別容易;
3. 容易管理
當網站頁面變得復雜時,頁面管理將變得非常重要,我們需要花很多精力在頁面架構和代碼維護上,而react 讓這一切變得簡單;
三、react不能幫我們做什么
react的目的是讓我們更好的管理和復用代碼,若自己要編寫react組件,那么基本的html標簽的應用,css語法都是必須要掌握的;使用react后我們依然需要做以下兩點:
1. 親自編寫所有要渲染的頁面,雖然不用使用html,但需要用類似的 JSX語法。react只是幫我們提高了復用性;
2. 親自寫所有的css代碼,頁面呈現效果依然需要自己分析編寫;
當然借助很多開源的react組件,可以取代一部分這些工作,不過做出的網站大都比較雷同,缺乏個性;
四、深入理解react究竟做了什么
對前端稍微有點基礎的都知道,前端學習有3大塊html+css+js,其中我們看到的所有web頁面的顯示效果只有兩個因素決定 ,即html和css;只要頁面發生了改變,無論是呈現的數據變了,圖表變了,圖片變了還是某 個顏色變了,無論這種改變是如何導致的,比如鼠標點擊,聲音控制或者后台數據改變。那么必然意味着 html或者css發生了改變;簡而言之,頁面的呈現和html+css有着一一對應的關系;而前端的主要工作,除了 編寫各種頁面之外,就是使用js語言根據數據來不斷地更新html和css,從而使頁面發生變化;
1. 原生開發如何更新頁面
當js以瀏覽器作為宿主環境時,瀏覽器為js提供了DOM作為js操作文檔的唯一接口,當不使用任何框架時,要更新頁面,我們必須親自調用DOM提供的API來更改文檔,效率極其低下;
2. react如何更新頁面
在react中每個組件都有一個state對象,它存儲了當前組件需要的所有可能發生變化的數據,渲染的html頁面和state中的數據是一種一一對應的關系。只要我們通過setState方法改變了state中的數據,那么html也 就跟着變化了,無需我們親自動手修改dom;在使用react時,只要我們根據state構建了組件,接下來只需要 考慮如何更新state即可。react為更新dom提供了非常高效的算法,這里不深入展開去講了;
五、react的基本用法
react組件的編寫需要兩類信息,變化的和不變的。在組件編寫時要花精力去分析哪些屬性在組件的生命周期 中是有可能發生變化的,哪些是不變的。不變的部分我們就可以寫死在html中,針對變化的部分其信息來源 有兩種 ,即組件的狀態和父組件的狀態;
1. 組件的狀態
在編寫組件時,要為組件編寫一個state屬性,存儲了當前組件需要的數據;當需要改變狀態時,調用當前組件的this.setState()方法即可,瀏覽器會自動重新渲染當前組件,下面是官方demo的一個例子:
class Square extends React.Component { constructor() { super(); this.state = { value: null, }; } render() { return ( <button className="square" onClick={() => this.setState({value: 'X'})}> {this.state.value} </button> ); } }
2. 父組件的狀態
當你遇到需要同時獲取多個子組件數據,或者兩個組件之間需要相互通訊的情況時,把子組件的 state 數據提升至其共同的父組件當中保存。之后父組件可以通過 props 將狀態數據傳遞到子組件當中。這樣應用當中 的狀態數據就能夠更方便地交流共享了。(官方文檔),官方示例如下:
1 //父組件 2 renderSquare(i) { 3 return ( 4 <Square 5 value={this.state.squares[i]} 6 onClick={() => this.handleClick(i)} 7 /> 8 ); 9 } 10 11 //子組件 12 class Square extends React.Component { 13 render() { 14 return ( 15 <button className="square" onClick={() =>this.props.onClick()}> 16 {this.props.value} 17 </button> 18 ); 19 } 20 }
小結:
state——組件的狀態屬性
setState——重新設置組件的狀態(這里注意,需要設置一個新的對象而不是在原有組件對象上做修改,至於原因,官方文檔上說的很清楚)
props——子組件通過這個屬性獲得父組件的信息
六、redux
1. 為什么要使用redux
redux是一個用來管理前端數據的一個架構,只有在應用程序非常復雜,數據來源復雜,交互頻繁的情況下, 應用redux才有明顯的好處;比如,某個應用有上百個組件,並且組件之間信息交互頻繁,如果不使用redux ,那么數據將會分散在上百個組件當中,並且當多個組件需要同一個數據時,同樣的數據在每個組件中將有 一個副本,當數據改變時,維護起來會相當麻煩。這種情況下就需要考慮引入redux;
2. redux設計的三大原則
(1) 單一數據源
使用redux的程序,所有的state都存儲在一個單一的數據源store內部,類似一個巨大的對象樹。
(2)state是只讀的
state是只讀的,能改變state的唯一方式是通過觸發action來修改
(3)使用純函數執行修改
為了描述 action 如何改變 state tree , 你需要編寫 reducers。reducers是一些純函數,接口是當前state和action。只需要根據action,返回對應的state。而且必須要有返回。
3. 主要API
store=createStare(reducer)——創建store
state=store.getState()
store.dispatch(action)——觸發action,這是改變state的唯一接口
store.subscribe(listener)——一旦State發生變化,就自動執行這個函數,只要把 View 的更新函數(對於 React 項目,就是組件的render方法或setState方法)放入listen,就會實現 View 的自動渲染。
4. reducer的拆分
Redux 提供了一個combineReducers方法,用於 Reducer 的拆分。你只要定義各個子 Reducer 函數,然后用這個方法,就可以將它們合成一個大的 Reducer。
七、react-redux
為了方便使用,Redux 的作者封裝了一個 React 專用的庫 React-Redux;React-Redux 將所有組件分成兩大 類:UI 組件(presentational component)和容器組件(container component),其中UI組件,是“純組件”,只負責呈現,所有數據通過props獲取;容器組件負責數據和邏輯。可以使用裝飾器模式把純組件轉化 為容器組價,這里主要用到了三個函數:
1. mapStateToProps(state,ownprops)
建立一個從(外部的)state對象到(UI 組件的)props對象的映射關系。
2. mapStateToProps(dispatch,ownProps)
用來建立store.dispatch方法到props對象的映射。
3.connect
React-Redux 提供connect方法,用於從 UI 組件生成容器組件。它需要mapStateToProps和mapStateToProps作為參數。例如:
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
<Provider> 組件
當組件嵌套比較深的時候,內層組件要獲得state會非常麻煩,需要借助props屬性一層一層傳遞。Proveder組件解決了這個問題,把Provider組件放在最外層,只要在Proveder上傳入store,這樣所有子組件都可以拿到state了
1 render( 2 <Provider store={store}> 3 <App /> 4 </Provider>, 5 document.getElementById('root') 6 )
八、react-router
一個應用程序往往不只一個頁面,在多頁面應用程序中我們需要在各個頁面之間切換,react-route架構提供了在多個頁面和組件之間進行切換的機制;react-router常用組件如下:
<BrowserRouter>
<Link>
為你的應用提供聲明式的、可訪問的導航鏈接。
--屬性 to
<Route>
最基本的職責是在其 path 屬性與某個 location 匹配時呈現一些 UI。
--屬性 path
--屬性 component
--exact完全匹配
<Switch>
只渲染命中的第一個路由
<Redirect>
直接渲染路由
--屬性 to
