实战分析
1、用户输入窗里的内容是保存在组件的state里,然后通过监听onchange,然后将输入的值setState。
类似于 <input />、<select />、<textarea> 这些元素的 value 值被 React.js 所控制、渲染的组件,在 React.js 当中被称为受控组件(Controlled Component)。对于用户可输入的控件,一般都可以让它们成为受控组件,这是 React.js 所推崇的做法。
状态提升
2、在我们的例子当中,如果把 comments 交给父组件 CommentApp ,那么 CommentList 和 CommentList2 都可以通过 props 获取到 comments,React.js 把这种行为叫做“状态提升”。
总结一下:当某个状态被多个组件依赖或者影响的时候,就把该状态提升到这些组件的最近公共父组件中去管理,用 props 传递数据或者函数来管理这种依赖或着影响的行为。(input会影响comments,list依赖comments,所以放到app组件里通过props一起管理)
你可以看到 React.js 并没有提供好的解决方案来管理这种组件之间的共享状态。在实际项目当中状态提升并不是一个好的解决方案,所以我们后续会引入 Redux 这样的状态管理工具来帮助我们来管理这种共享状态,但是在讲解到 Redux 之前,我们暂时采取状态提升的方式来进行管理。
对于不会被多个组件依赖和影响的状态(例如某种下拉菜单的展开和收起状态),一般来说只需要保存在组件内部即可,不需要做提升或者特殊的管理。
挂载阶段的组件生命周期
3、我们把 React.js 将组件渲染,并且构造 DOM 元素然后塞入页面的过程称为组件的挂载。
例如,ReactDOM.render(
<Header />,
document.getElementById('root')
)
这样一个组件的挂载过程:1、React.createElement 中实例化一个 Header;2、React.createElement 中调用 header.render 方法渲染组件的内容;3、ReactDOM 用渲染后的 JavaScript 对象来来构建真正的 DOM 元素;4、ReactDOM 把 DOM 元素塞到页面上。
这是一个从无到有的过程,React.js 提供一些生命周期函数可以给我们在这个过程中做一些操作。具体如下:
-> constructor()
-> componentWillMount():组件挂载开始之前,也就是在组件调用 render 方法之前调用。
-> render()
// 然后构造 DOM 元素插入页面
-> componentDidMount():组件挂载完成以后,也就是 DOM 元素已经插入页面后调用。
// ...
// 即将从页面中删除
-> componentWillUnmount():组件对应的 DOM 元素从页面中删除之前调用。
// 从页面中删除
4、总结:
我们一般会把组件的 state 的初始化工作放在 constructor 里面去做;
在 componentWillMount 进行组件的启动工作,例如 Ajax 数据拉取、定时器的启动;
组件从页面上销毁的时候,有时候需要一些数据的清理,例如定时器的清理,就会放在 componentWillUnmount 里面去做。
而 componentDidMount ,一般来说,有些组件的启动工作是依赖 DOM 的,例如动画的启动,在 componentWillMount 的时候组件还没挂载完成,所以没法进行这些启动工作,这时候就可以把这些操作放在 componentDidMount 当中。
更新阶段的组件生命周期
5、除了挂载阶段,还有一种“更新阶段”。说白了就是 setState 导致 React.js 重新渲染组件并且把组件的变化应用到 DOM 元素上的过程,这是一个组件的变化过程。而 React.js 也提供了一系列的生命周期函数可以让我们在这个组件更新的过程执行一些操作。需要对 Virtual-DOM 策略有比较深入理解才能完全掌握。https://github.com/livoras/blog/issues/13
这里为了知识的完整,补充关于更新阶段的组件生命周期:
shouldComponentUpdate(nextProps, nextState):你可以通过这个方法控制组件是否重新渲染。如果返回 false 组件就不会重新渲染。这个生命周期在 React.js 性能优化上非常有用。
componentWillReceiveProps(nextProps):组件从父组件接收到新的 props 之前调用。
componentWillUpdate():组件开始重新渲染之前调用。
componentDidUpdate():组件重新渲染并且把更改变更到真实的 DOM 以后调用。