Open HuangHongRui opened 7 years ago
注意,并不是每个组件都需要定义自己的构造函数。 无状态的React组件 是不需要定义构造函数的。
一个组件需要构造函数,为了如下目的:
在Es6语法下,类的每个成员函数在执行时的this并不是和类实例自动绑定的!!! 而在构造函数中,this就是当前组件实例,所以为了方便后面调用,往往在构造函数中将这个实例的特定函数绑定this为当前实例。
getInitialState
此函数的返回值会用来初始化组件的 this.state.(只出现在装载过程,整个生命周期过程中,这个函数只被调用一次)
getDefaultProps
函数的返回值可作为 props 的初始值.
【两个方法在Es6的方法定义的React组件根本不会用到,而且都只有在用React.creatClass(废弃)方法创造组件类才会发生作用。】
render 函数是组件中最重要的函数!!!
React组件可以忽略其他所有函数不实现,但定要实现render函数,
因所有组件的父类React.Component
对除render之外的生命周期函数都有默认实现。
一个组件要发挥作用,总要渲染一些东西, render函数并不做实际的渲染动作, 它只是返回一个JSX描述的结构, 最终由React来操作渲染过程。
某些特殊组件的作用不是渲染界面,或者,组件在某些情况下选择没有东西可画, 那就让render函数返回一个 null 或 false,等于告诉React 这个组件这次不需渲染任何DOM元素
render函数应该是一个纯函数,完全根据 this.state 和 this.props 来决定返回的结果, 而且不要产生任何副作用副作用。 在render函数中去调用this.setState 毫无疑问是错误的 因为一个纯函数不应该引起状态的改变。
[ componentWillMount 和 componentDidMount ]
在装载过程中,
componentWillMount
会在调用rnder函数之前被调用,
componentDidMount
会在调用render函数之后被调用,
这两个函数把render函数夹住,分别做render前后必要的工作。
通常不定义componentWillMount
函数,
因为将要装载的时候,这时没有任何渲染出来的结果,即使调用this.setState
修改状态也不会引发重新绘制,一切都迟了
换句话说,所有在componentWillMount
中做的事情,都可提到constructor
中去做。(可认为它的出现存在只是为了和componentDidCount
对称
render函数被调用完之后,componentDidMount
函数并不是会被立刻调用,
componentDidMount
被调用时,render函数返回的东西已经引发了渲染,
组件已经被装载到了DOM树上。
以Counter 中的代码为例,其console.log出的一些内容:
可看到,componentWillMount
都紧贴着组件的render之前被调用,
而componentDidMount
是当所有组件render函数调用之后,
所有(三个)组件的componentDidMount
再一起被调用。
上面的现象,是因 rende 函数并不往 DOM 树上渲染或者装载内容, 它只返回一个 JSX 表示的对象!!! 再由 React 库来根据返回的对象决定如何渲染!
【而 React 库肯定要把所有组件返回的结果综合起来,才能知道如何产生对应的DOM修改。所有只有React库调用三个Counter组件的函数之后,才有可能完成装载,这时猜依次调用各个组件的componentDidMount
函数作为装载函数作为收尾。。
componentDidMount
只能在浏览器被调用 / 而componentWillMount
还可在服务器端被调用。。
既然装载是一个创建组件并放到DOM树上的过程,真正的装载是不可能在服务器端完成的,因为服务器端渲染不会产生DOM树,通过React组件产生的只是一个纯粹的字符串。
componentDidMount
被调用时,组件已经被装载到了DOM树上,可以获取渲染出来的任何DOM。
实际开发过程,可能会让React和其他UI库配合使用,例如jQuery等, 有时某些UI库在做某些功能比React更合适。 如果真要让React和jQuery配合,需要利用componentDidMount函数, 当该函数被执行时,组件对应的DOM已存在,所有的事件处理函数也已设置好, 此时可调用jQuery代码,让jQuery代码在已绘制的DOM基础上增强新功能。
在componentDidMount
中调用jQuery代码只处理了装载过程,要和jQuery完全结合,
需要再考虑React的更新过程——componentDidUpdate
函数
[ 更新过程 ]
当 props 或 state 被修改时,会引起组件的更新过程。
更新过程一次调用下面的生面周期函数:
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
不是所有的更新过程都会执行全部函数。
componentWillReceiveProps
函数。通过this.setState 方法触发的更新不会调用 componentWillReceiveProps
这个函数, 因为该函数适合根据新的props值(参数nextProps)来计算出是不是要更新内部状态state。
更新内部状态的方法是this.setState
,如果调用导致componentWillReceiveProps
再次被调用,那就是死循环了。
每个React组件都可通过 forceUpdate
函数强行引发一次重新绘制。
componentWillReceiveProps
函数有必要吧传入的参数 nextProps 和 this.props 作必要对比。
nextProps 代表这一次渲染传入的Props值
this.Props代表上次渲染时的Props值
只有两者有变化的时候才有必要调用this.setState更新内部内容.
**React的组件组合中, 可以只渲染一个子组件,其他组件不需要渲染,这是提高React性能的重要方式。
shouldComponentUpdate(nextProps, nextState)
除了 render 函数,shouldComponentUpdate 是 React 组件生命周期中最重要的一个函数了。
说render
重要是因为 render
决定了该渲染生命,
而shouldComponentUpdate
重要是因它决定一个组件什么时候不需要渲染.
render
和shouldComponentUpdate
是React生命周期中2个唯一要求返回结果的函数。
render返回结果将用于构造DOM对象
shouldComponentUpdate`返回一个布尔值,告诉React库这个组件在此次更新过程中是否继续。
更新过程中,React 首先调用 shouldComponentUpdate
如果返回true 那么继续更新然后调用render,如果返回false,那就停止更新过程,不会引发后续渲染。
重要性: 因为只要使用恰当,能够大大提高React的性能。
shouldComponentUpdate
根据props
和state
值两参数,加上this.props
和this.state
来判断并返回结果。
如果给组件添加该函数,会默认实现简单返回true,就是每次更新过程都会重新渲染,这是求稳方式。 若要追求更高新能,那需要定制这个函数。
shouldComponentUpdate(nextProps, nextState) {
return (nextProps.caption !== this.props.caption) ||
(nextState.count !== this.state.count)
}
只有当 caption
或者 state 中的 count
值改变, 才会返回true
执行shouldComponentUpdate
时,this.state
依然是this.setState
函数执行之前的值,实际上要做的就是在 nextProps
nextState
this.props
和this.state
中互相对比
在实际开发中遇到潘达复杂的组件,这种情况下避免没必要的渲染会大大提高性能。
componentWillUpdate
和 componentDidUpdate
和装载过程不同,当服务器使用React渲染时这一对函数中的Did函数,并不只是在浏览器端才执行,无论更新过程发生在服务器端还是浏览器端,该函数都会被调用。。。
前面的 componentDidMount
函数执行其他UI库的代码,当React组件被更新时,原有内容被重新绘制,此时就需要在componentDidUpdate
函数再次调用UI库的代码。。
*使用服务器端渲染时,基本不会经历更新过程,因服务器端只需要产出HTML字符串,一个装载过程就足够产出HTML了,正常情况下服务器不会调用componentDidUpdate
。
[ 卸载过程 ]
React组件的卸载过程涉及函数——componentWillUnmount
当React 组件要从 DOM树上 删除掉前触发。适合做些请理性工作。
componentWillUnmount 的工作 跟 componentDidMount 有关, 例如componentDidMount使用非React方法创造一些DOM元素,如果不管可能会造成内存泄露, 这时就需要componentWillUnmount来把这些Dom清理掉...
起到一个收尾的作用
[ React 组件 state 和 prop 的局限 ]
数据管理问题
如果父组件 和 子组件 数据发生了重复,带来一个问题就是如何保证充足的数据一致。
如何处理这种问题呢?
把数据源放在React组件之外形成全局状态。。
Flux 和 Redux 中的 store
为了理解React 的工作过程, 必须要了解 React 组件的生命周期。。。
每个组件在网页中也会被创建/更新和删除: React 严格定义了组件的生命周期,可能经历如下三个过程:
三种不同的过程,React库会依次调用组件的一些成员函数, 这些函数称为 生命周期函数
[装载过程] 当组件第一次被渲染时,依次调用的函数如下: