剛爲祖國母親慶完生,眼看假餘額就要不足了,小夥伴們玩的是否開心呢,反正我是死宅在家,沒出去玩,在家也沒好好學習,實屬慚愧。這不,今天和你們分享下關於 react 驅動 ui 更新的幾種方式,都說 react 是單向數據流,數據驅動 ui,那麼你知道在 react 中有幾種驅動視圖更新的方式呢。react
setState 是衆所周知最多見的更新視圖的方式了,只須要給個初始 state,須要更新的時候調用 this.setState, 組件會經歷 shoudlComponentUpdate
=> componentWillUpdate
=> render
=> componentDidUpdate
四個過程,若是沒有在 shouldComponentUpdate 中手動 return false 的狀況下,那麼 ui 此時就會更新。jquery
須要注意的是,儘管 this.setState({}) 參數爲空對象時,react 同樣會更新,調用上面的四個生命週期,只是 ui 視圖不有會變化。redux
固然這些都要基於 class 組件,由於 setState 是 Component 原型上的方法,必須得是繼承 Component的組件才能調用 this.setState。(以前有寫過一篇關於setState的文章,感興趣的大佬也能夠去看看。)app
Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate(). This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate() method of each child. React will still only update the DOM if the markup changes.dom
官方說的比較清楚,調用 forceUpdate 後當前組件會跳過 shouldComponentUpdate 這個鉤子,儘管手動 return false,也同樣會更新,單詞字面理解也是強制更新,可是須要注意的是,子組件的更新仍是會受到 shouldComponentUpdate 控制。函數
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().post
forceUpdate的使用場景通常是視圖更新來源於其餘非 state、props的數據,好比綁定在 組件實例上的屬性,或者是直接修改 this.state.xxx = xxx ,而後調用 this.forceUpdate(),不過官方不建議這麼作,正常狀況下應該避免使用 forceUpdate,經過 state 或者 props 去更新視圖。性能
在 react 中不免會有操做原生 dom 的時候,好比你用了第三方好比 jquery 這種須要獲取 dom 的庫,或者你須要實現一個拖拽,雙指縮放的組件,對於這些,你也許能夠用操做的 dom 的方式繞過 react 的 setState 再到 dom diff 一系列的計算,直接更新 dom ,提升些許性能。學習
以上三種更新 ui 的方式,我這邊有個Demo, 須要注意的是,當經過 setState 更新改變顏色變紅,在點擊原生 dom 按鈕改變顏色變綠,這時在點擊 setState 的按鈕,發現視圖不更新,可是仍是走了 render 函數,這是由於點擊原生 dom 按鈕前, this.state.backgroundColor 值是 red,原生操做是直接改變的 dom style,在點回 setState 按鈕,其實 this.state.backgroundColor的值仍是 red, 雖然走了更新邏輯,可是因爲 react 的 新老 virtual dom 對比的時候,發現顏色並沒改變, 致使沒有 patch 到 ui 上。ui
上面的幾種方式都是經過 react 自己自帶的 state 去更新 ui, 當項目中使用 redux 時, 咱們通常會經過 dispach 一個 action, 改變 store,而後更新 ui,dispatch action 是經過改變 props 去驅動視圖的,你們在使用的時候有沒有想過爲何 this.props.dispatch({ type: 'xxx' }), 就能夠驅動 ui 視圖更新呢?
這邊簡單的講下,當咱們dispatch 一個 action 的時候, 調用的實際上是 store.dispatch,這個都沒問題,store.dispatch 會去跑一遍全部註冊在 createStore 中的 reducer, 找到對應的 type 更新數據,返回一個新的 state。
而咱們的組件想拿到 store 的數據必須經過 connect(mapStateToProps, mapDispatchToProps)(App) 像這樣,react-redux 中的 Connect 組件會在 componengDidMount 的時候去 調用 一個 trySubscribe
的方法,其內部調用 store.subscribe 去訂閱一個 handleChange
的方法。
因此當你 dispatch action 的時候,就會觸發 Connect 組件中的方法, Connect 組件中也維護了一個叫作 storeState
的 state,每次拿到新的 sotre 就去調用 setState, 觸發 render 函數, render 函數會根據你 connect 中傳入的 mapStateToProps, mapDispatchToProps,包括可選參數 mergeProps, 去作一個 props 的合併動做, 最終在 Connect 組件內部 return 出來一個 createElement(WrappedComponent,this.mergedProps)
這樣的東西,而 createElement 第二個參數就是你組件的 props, 那麼每次 props 變了,就會驅動視圖的更新。這就是 Redux 其中的中作原理,固然這邊描述的比較簡短, 下次單獨寫一篇關於 react、 redux、 react-redux 的文章。