聊一聊 React 中更新 ui 视图的几种方式

前言

刚为祖国母亲庆完生,眼看假余额就要不足了,小伙伴们玩的是否开心呢,反正我是死宅在家,没出去玩,在家也没好好学习,实属惭愧。这不,今天和你们分享下关于 react 驱动 ui 更新的几种方式,都说 react 是单向数据流,数据驱动 ui,那么你知道在 react 中有几种驱动视图更新的方式呢。react

1. setState

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

2. forceUpdate

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 去更新视图。性能

3. 原生操做dom

在 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

4. dispatch action

上面的几种方式都是经过 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 的文章。

总结

  1. 经过调用 this.setState 改变 state 驱动视图。
  2. 经过调用 this.forceUpdate 强制更新视图。
  3. 经过操做原生 dom 更新视图。
  4. 经过改变 props 驱动视图(redux 或者 修改父子组件传递 props )。
相关文章
相关标签/搜索