内容简介:组件首先,什么是普通属性?我们的组件都是使用
组件 state
必须能代表一个组件UI呈现的完整状态集,即组件的任何UI改变都可以从 state
的变化中反映出来;同时, state
还必须代表一个组件UI呈现的最小状态集,即 state
中的所有状态都用于反映组件UI的变化,没有任何多余的状态,也不应该存在通过其他状态计算而来的中间状态。
state vs 普通属性
首先,什么是普通属性?
我们的组件都是使用 ES6
的 class
定义的,所以组件的属性其实也就是 class
的属性(更确切的说法是 class
实例化对象的属性,但因为JavaScript本质上是没有类的定义的, class
只不过是 ES6
提供的语法糖,所以这里模糊化类和对象的区别)。
在 ES6
中,可以使用 this.{属性名}
定义一个 class
的属性,也可以说属性是直接挂载到 this
下的变量。因此, state
、 props
实际上也是组件的属性,只不过它们是 React
为我们在 Componentclass
中预定义好的属性。除了 state
、 props
以外的其他组件属性称为组件的普通属性。
比如,组件中需要一个定时器来自动更新显示时间时,我们都会需要一个 timerId
来保存该定时器,已在需要的能够清除它。这就是一个普通的属性,因为它和组件要渲染的内容没有直接关系。
因此,当我们在组件中需要用到一个变量,并且它与组件的渲染无关时,就应该把这个变量定义为组件的普通属性,直接挂载到 this
下,而不是作为组件的 state
。或者更直观的判断是, 看组件render方法中是否使用到了这个变量,如果没有,它就是一个普通属性
。
state vs props
state
和 props
又有什么区别呢?
state
和 props
都直接和组件的UI渲染有关,它们的变化都会触发组件重新渲染,但 props
对于使用它的组件来说是只读的,是通过父组件传递过来的,要想修改 props
,只能在父组件中修改;而 state
是组件内部自己维护的状态,是可变的。
其实区分 state
和 props
的关键就是,‘控制权’是在组件自身,还是由其父组件来控制的。
state的判断依据
(1)这个变量是否通过 props
从父组件中获取?如果是,那么它不是一个状态。
(2)这个变量是否在组件的整个生命周期中都保持不变?如果是,那么它不是一个状态。
(3)这个变量是否可以通过其他 状态(state)
或者 属性(props)
计算得到?如果是,那么它不是一个状态。
(4)这个变量是否在组件的 render
方法中使用?如果不是,那么它不是一个状态。这种情况下,这个变量更适合定义为组件的一个普通属性。
state的修改
1、state不能直接进行修改
直接赋值形式修改state,不会触发组件的render。修改 state
需要通过 setState
方法进行修改。
2、state的更新是异步的
调用 setState
时,组件的 state
并不会立即改变, setState
只是把要修改的状态放入一个队列中, React
会优化真正的执行时机,并且出于性能原因,可能会将多次 setState
的状态修改合并成一次状态修改。
所以不要依赖当前的 state
,计算下一个 state
。当真正执行状态修改时,依赖的 this.state
并不能保证是最新的 state
,因为 React
会把多次 state
的修改合并成一次,这时 this.state
还是这几次 state
修改前的 state
。
另外,需要注意的是,同样不能依赖当前的 props
计算下一个状态,因为 props
的更新也是异步的。
如,电商类购物车添加购买数量时,如果连续点击两次,就会连续调用两次 this.setState({count:this.state.count+1})
,在 React
合并多次修改为一次的情况下,相当于等价执行了下面的操作:
于是,最终只会增加一次操作的值。
如果有这样的需求,可以使用另一个接收一个函数作为参数的 setState
,这个函数有两个参数,第一个是当前最新状态(本次组件状态修改生效后的状态)的前一个状态 preState
(本次组件状态修改前的状态),第二个参数是当前最新的属性 props
。代码如下:
3、state更新是一个合并的过程
我们在每次调用 setState
修改state时,并不是需要把所有的值都进行修改,而只是设置我们要修改的部分值。 React
会合并新值导员的组件 state
中,同时保留没有发生变化的原来的 state
的值。
state与不可变对象
React
官方建议把 state
当作不可变对象,一方面,直接修改 this.state
,组件并不会重新 render
;另一方面, state
中包含的所有状态都应该是不可变对象。当 state
中的某个状态发生变化时,应该重新创建这个状态对象,而不是直接修改原来的状态。
可以分为下面三种情况:
1.状态的类型是不可变类型(数字、字符串、布尔值、null、undefined)
2.状态的类型是数组
当从数组中截取部分元素作为新的状态时,可使用数组的 slice
方法:
当从数组中过滤部分元素作为新的状态时,可使用数组的 filter
方法:
注意,不要使用 push、pop、shift、unshift、splice
等方法修改数组类型的状态,因为这些方法都是在原数组的基础上修改的,而 concat、slice、filter
会返回一个新的数组。
3.状态的类型是普通对象(不包含字符串、数组)
(1)使用 ES6
的 Object.assgin
方法:
(2)使用对象扩展语法(object spread properties):
总结一下,创建新的状态对象的关键是,避免使用会直接修改原对象的方法,而是使用可以返回一个新对象的方法。当然,也可以使用一些 Immutable
的JS库(如 Immutable.js
)实现类似的效果。
为什么 React
推荐组件的状态是不可变对象呢?一方面是因为对不可变对象的修改会返回一个新对象,不需要担心原有对象在不小心的情况下被修改导致的错误,方便程序的管理和调试;另一方面是出于性能考虑,当对象组件状态都是不可变对象时,在组件的 shouldComponentUpdate
方法中仅需要比较前后两次状态对象的引用就可以判断状态是否真的改变,从而避免不必要的 render
调用。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- React 组件模式-有状态组件 x 无状态组件、容器组件 x 展示组件、高阶组件 x 渲染回调(函数作为子组件)
- Serverless 组件开发尝试:全局变量组件和单独部署组件
- angular自定义组件-UI组件篇-switch组件
- React Hooks 源码解析(一):类组件、函数组件、纯组件
- Vue动态组件和异步组件
- Vue 动态组件 & 异步组件原理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入分析Java Web技术内幕(修订版)
许令波 / 电子工业出版社 / 2014-8-1 / CNY 79.00
《深入分析Java Web技术内幕(修订版)》新增了淘宝在无线端的应用实践,包括:CDN 动态加速、多终端化改造、 多终端Session 统一 ,以及在大流量的情况下,如何跨越性能、网络和一个地区的电力瓶颈等内容,并提供了比较完整的解决方案。 《深入分析Java Web技术内幕(修订版)》主要围绕Java Web 相关技术从三方面全面、深入地进行了阐述。首先介绍前端知识,即在JavaWeb ......一起来看看 《深入分析Java Web技术内幕(修订版)》 这本书的介绍吧!