最近正在学习react,在看《深入浅出react和redux》这本书,感觉还不错,内容浅显易懂。就打算做一下学习笔记,免得到时候七忘八忘
一、组件数据
(1)props和state
子组件访问外部的父组件,需要通过props才能获取父组件传递的内容,他是组件的对外接口。可以传函数,也可以是属性,但是不可以修改props;而state用于内部状态数据的使用。
(2)接口规范
组件对外声明了,我支持哪些prop,又需要什么样的格式。虽然这是一种限制,但是对于propTypes
的检查,可以很容易发现错误的引用方式,可尽早发现代码错误,举个栗子:
ChildrenComponent.propTypes = {
initValue : propTypes.number.isRequired,
str: propTypes.string
modify: propTypes.func
}
以上代码指定了,initValue
是数值类型,且当使用isRequired
时则表示这个属性是必须的,同理str
指定字符串类型,modify
指定函数类型。
需要注意的是,如果不使用声明,对组件没有影响,就算是错误引用也不会报错的。
这些声明必定是要占用内存资源的,目的只是为了辅助开发。在生产环境中,这些并没有意义,在正式发布的时候,可以npm
安装babel-react-optimize
抹除propTypes
。
(3)props默认声明
在子组件中,对父组件传递过来的属性,存放到state中,但是如果像str
,则不一定有传递这个属性,所以要加上逻辑判断。
constructor(props) {
this.state = {
title: props.str || ""
}
}
但是如果属性很多,就会造成逻辑充斥代码,我们可以再子组件中提前声明默认props值。
ChildrenComponent.defaultProps = {
str: ""
}
// 父组件
this.state = {
title: props.str
}
(4)setState
在开发中,我们可以发现,对state属性赋值的时候,如果使用this.state.属性 = xxx
,则发现页面上的数据没有发生变化,而正确的做法是使用this.setState({属性: xxx})
。
this.state
赋值的方式只是暴力地修改了组件内部的状态,并没有驱动组件进行重新渲染,而setState
可以做到这一点。
二、组件生命周期
(1)装载过程
当组件第一次被渲染时候。函数的调用次序:
-
constructor
当创造一个组件的实例时,必定会执行构造函数,在这里可以初始化state,绑定成员的this环境。
constructor(props) { super(props); this.incrementBtn = this.incrementBtn.bind(this); this.state = { count: props.initValue } }
-
getInitialState
使用
React.createClass
创造组件时使用的,返回值用来初始this.state
。 -
getDefaultProps
使用
React.createClass
创造组件时使用的,返回值用来设置默认的props。 -
componentWillMount
在render渲染之前执行,此时没有渲染任何东西,在这边做的事都可以挪到constructor中去做。
-
render
一个组件的灵魂(必不可少的部分),渲染界面。
-
componentDidMount
render函数被调用之后,这个函数并不会立马被调用,而是会等到引用该组件的父组件中的render函数全部渲染之后,最后依次调用各个子组件的
componentDidMount
,并且只会在浏览器端执行。
(2)更新过程
注意:并不是所有的更新都会执行下面的函数
-
componentWillReceiveProps
当父组件的render被调用时,子组件也会相应地跟新,此时不管传给子组件的props是否发生变化,都会触发。所以props变化是触发这个函数的充分不必要条件。
-
shouldComponentUpdate
根据state前后数据和props前后数据来决定一个组件需不需要被重新渲染,返回结果为boolean值,如果为true,则会调用
componentWillUpdate、render、 componentDidUpdate
函数,否则都不会执行。主要作用:减少不必要的重新渲染,提高性能。
shouldComponentUpdate(nextProps, nextState) { return (nextProps.title !== this.props.title} || (nextState.sum !==this.state.sum); }
componentWillUpdate
render
componentDidUpdate
这三个函数执行过程与装载过程最后三个类似
(3)卸载过程
-
componentWillUnmount
当组件从DOM树上删除后,就会被调用,用于做清理工作
三、向外传递数据
当父组件想要获取子组件的prop时,可以传递给子组件一个提前定义好的函数,而子组件只需要通过prop调用函数,并传递参数,父组件就能获取。但是通过propTypes
不能限制函数的参数格式,还是要需要自己多注意。
state和prop的局限性
- 当组件和父组件中的数据有了重复,如果由于某种原因导致数据不一致,比如回调没有执行,那么就会出现问题,这时候应该要有一个全局的状态来保持一致,来作为唯一可靠的数据来源。
- 如果祖父组件想要传递数据给孙子组件,那么还要经过父组件,可能这个数据对父组件根本没啥用,但也得乖乖中转
要解决这些问题就要靠flux和redux的Store了。