Component 中 state 和 props 的区别;
组件Component中状态state和属性props的区别
state | props |
---|---|
state是在组件内部定义的一个特殊对象{} ,既起到组件内部的一种缓存作用, 也具备由于state变化而激发生命周期中渲染的方法 render()被回调的作用。且使用域仅限于组件内部。 | props是组件属性,连接了外部父组件和组件内部的使用域。 它的改变激发声明周期方法componentWillReceiveProps(nextProps) 和渲染的方法render()逐次被回调。连接外部父组件, 可以通过父组件向其传递value、function等,连接内部组件, this.props缓存了当前组件的所有props属性内容 即 {value, function}=this.props; |
代码解释 props
/**
* 通过封装 FlatList 自定义一个列表组件
*/
export default class MyFlatList extends Component {
constructor(props) {
super(props);
}
...
/**
*象组件FlatList中的
*ref、ListHeaderComponent、ItemSeparatorComponent、
*data、keyExtractor、onRefresh、refreshing等都是props属性;
*
* 象这种样式的定义 this.props.itemSeparator、
* this.props.onRefresh、this.props.refreshing、this.props.onLoadMore等
* 属于自定义组件MyFlatList的属性,是我们依照FlatList所定义的。
* 类似象外部开放的接口一样,就像这里FlatList使用自己的
* 属性ListHeaderComponent、ItemSeparatorComponent、data等一样来使用;
* @returns {XML}
*/
render() {
return (<View style={{flex: 1, backgroundColor: Colors.bg}}>
<FlatList
ref={(flatlist) => this.flatlist = flatlist}
ListHeaderComponent={this._header}
renderItem={this._renderItem}
ItemSeparatorComponent={this.props.itemSeparator}
data={this.props.data}
keyExtractor={this._keyExtractor}
onRefresh={this.props.onRefresh}
refreshing={this.props.refreshing}
onEndReachedThreshold={0.1}
onEndReached={this.props.onLoadMore}
initialNumToRender={3}
getItemLayout={(data, index) => ({
length: 250, offset: (250 + 10) * index, index
})}
/>
</View>);
}
}
这是使用MyFlatList,来看下它的这个props
export default class FlatlistScreen extends Component {
...
/**
*这里MyFlatList的 itemSeparator、data、onRefresh 、refreshing 、onLoadMore
*就是FlatList中使用this.props.xxx来定义的。
* @returns {XML}
*/
render() {
return (<View style={styles.container}>
...
<MyFlatList
{...this.props}
itemSeparator={() => this.separator()}
data={this.state.dataSource}
onRefresh = {()=>this.onRefresh()}
refreshing = {this.state.isRefresh}
onLoadMore = {()=>this.onLoadMore()}
/>
</View>);
}
}
除了以上,如果是对数据内容的props属性的变化,如上面代码的data变化,必然会激发MyFlatList组件生命周期方法componentWillReciveProps回调,这里我们可以在render方法回调前,对数据再次进行判断处理。
**这就是props属性功能和作用!!**
代码解释 state
export default class FlatlistScreen extends Component {
constructor(props) {
super(props);
this.unmount = false;
this.state = ({
dataSource : [],
isRefresh: true,
});
}
...
/**
* 功能:使用箭头函数,不使用bind;因为bind函数每调用一次就会创建一个新的函数
*/
onRefresh() {
this.setState({
isRefresh: true,
});
//功能:制造刷新效果
this.interval = setInterval(() => {
clearInterval(this.interval);
//功能:制造上拉加载更多的效果
const data = [];
for (let i = 0; i < 8; i++) {
data.push({id: i, title: '亲子旅游日带娃儿玩' + i + '折起', state: '已过期', date: '2018/06/0' + (i - 8)},)
}
this.setState({
dataSource: data,
isRefresh: false,
});
}, 2000)
}
...
render() {
return (<View style={styles.container}>
...
<MyFlatList
{...this.props}
itemSeparator={() => this.separator()}
data={this.state.dataSource}
onRefresh = {()=>this.onRefresh()}
refreshing = {this.state.isRefresh}
onLoadMore = {()=>this.onLoadMore()}
/>
</View>);
}
}
看构造方法这里
this.state = ({
dataSource : [],
isRefresh: true,
});
这就是state的定义方式。通过改变dataSource、isRefresh的值就能激发render再次渲染组件。
比如这里的onRefresh方法使用了
this.setState({
dataSource: data,
isRefresh: false,
});
来控制改变state的时机,来控制组件渲染的时机。
**这就是状态state的使用!!**
react-native 与 Redux 的配合使用;
在Redux使用中,一些必知的概念
Redux | state | action | reducers |
---|---|---|---|
Redux 是 JavaScript 状态容器, 提供可预测化的状态管理。 使用 Redux 的一个益处, 就是它让 state 的变化过程变的可预知和透明。 | 以一个对象树的形式储存在于一个单一的 store 中, 惟一改变 state 的办法是触发 action。 | 一个描述发生什么的指示器对象。 action 内必须使用一个字符串类型的 type 字段, 来表示将要执行的动作。 且应该尽量减少在 action 中传递的数据; | 描述 action 如何改变 state 树。 reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。 |
这里是我基于Redux实现的已给简单操作流程源码
结合源码+图例,分析下redux的执行操作流程,解读redux是怎样原理!
登录操作执行图
现在定位在登录页面,处于未登录状态,需要点击登录操作。
图并结合源码分析
登录页面的部分源码,展示了登录页面的UI
从源码中50行看到,点击登录按钮,则调用方法login()
,而login()这个方法是从this.props
中解构赋值拿出来的,就是源码37行所示。
疑问1? this.props
中的login()是从哪里来的,怎么会在this.props中?!
接着看同一js文件中的代码片段
这里有一个方法非常的重要connect()
,她是干什么的,这里可以解答。
简单的说是,就我们所看到的代码从64到74行,connect()里面有两个回调函数,第一个回调的是state(Login页面的state),第二回调的是dispatch(Login页面用来进行分发登录操作的Action)。通过connect()()
实现了 回调函数中 status、isSuc、user 和 login() 他们与当前的组件(登录页面)的this.props绑定,也就是他们被注入到了this.props中。
所以,点击登录的执行流程是这样的:
点击登录按钮——>调用this.props中的login方法——>派发登录操作的action ——>.. reducer处理…导致store的state树中登录组件的state发生变化 … ——>源码中65行执行回调,同时UI将会执行重新的刷新、渲染——>渲染过程中需要的内容,从回调中的state中获取、赋值。
继续深入…
登录功能的Action中有两类内容,一是需要传递的用户数据对象
二是派发的Action构建函数
图中可以清晰看到,Action有两种实现方式,其中最后一种是异步的Action构建函数,前面则是同步的Action构建函数;通常异步的Action中会调用同步的Action。而同步的Action有一个特点就是有一个约定成俗的字段叫type,标识着Action的通知类型。
当执行登录操作,使用redux进行登录操作的action进行派发的时候,调用了异步的Action,异步的通知由在内部执行异步操作,调用同步的action。执行到这里,action就会被分发到哪里呢??reducer
reducer也分为两部分,一是登录页面内容展示登录组件的state
是一个登录操作在执行到reducer时的处理,进行复制、赋值、填充的state模型的数据对象,store树中的一个对象。
reducer的处理也很简单,就是根据action的指定处理方式type,进行处理。处理完成之后,返回一个新的state对象。看源码是不是这样的?!
执行处理到这里,想到你已经发起疑问了。疑问2?总觉得,到reducer处理之后与组件容器那儿回调,直到页面再次渲染,没有什么关联??!它们到底是怎么建立关系的呢?
当然是通过Redux,以及处理异步action需要用到的中间件(标准的做法是使用 Redux Thunk 中间件)。
看这里,首先是集合管理action的处理,对reducer的管理
然后把对reduer的管理,以及处理结果再交给redux
并且也同时,把上面的两个reduer对应的处理结果state,作为store树的分支,绑定到了store中,进行统一管理和处理。而且还有一点很关键、很重要!也是急需解决的重要疑问——store树长什么样子??
经过我的实践和测试对比得出结论,
store树
中的登录组件的state,其数据内容的样子是和上图中源码第10行
rootReduer
中的数据结构LoginIn是对应的。也就是说他们是互相映射的。即,
store与rootReduer
在数据结构上是一致的,
store树
就是通过这样的
rootReduer
中一条条
{key:value}
数据拼凑到一起所组成的对象。
如果有点疑问,自己可以动手试一试,并用下图再加深下印象
store树是用来管理组件state数据的,好,因为我们使用了全局提供store的方式进行了处理,
store中的属性,我们可以在项目中进行全局使用。
所以,在connect()()
代码块中,当state发生变化,产生回调,我们可以通过state.LoginIn.status、state.LoginIn.isSuc、state.LoginIn.user来指定拿到当前组件对应的state数据。而state.LoginIn的调用方式就是从store树中取出LoginIn对应的state,而LoginIn是哪来的?也许内容有点多,蒙圈了,其实就在原先这里第11行代码。
所以,我之前总结的结论,store树中的登录组件的state,其数据内容的样子是和上图中源码第10行
rootReduer
中的数据结构LoginIn是对应的。也就是说他们是互相映射的。
store与rootReduer 在数据结构上是一致的, store树 就是通过这样的rootReduer 中一条条 {key:value} 数据拼凑到一起所组成的对象。
是正确的!到这里则回答了上面的疑问2?,同时也解决了Redux的使用以及执行原理。