理解
- 组件从创建到死亡它会经理一些特定的阶段
- React组件中包含一系列勾子函数(生命周期回调函数),会在特定的时刻调用
生命周期(旧)
挂载时
constructor -> componentWillMount -> render -> componentDidMount -> componentWillUnmount
组件更新时
-
常规流程:componentWillReceiveProps -> shouldComponentUpdate -> componentWillUpdate -> render -> componentWillUnmount
-
调用this.setState: shouldComponentUpdate -> componentWillUpdate -> render -> componentWillUnmount
-
调用this.forceUpdate: componentWillUpdate -> render -> componentWillUnmount
- shouldComponentUpdate 是控制组件更新的阀门,true为允许更新,false为阻止更新
- 当使用this.forceUpdate后,即使shouldComponentUpdate为false也会更新组件状态
- shouldComponentUpdate 如果没有自定义的话,默认返回值为true
class Count extends React.Component{
// 构造器
constructor(props){
console.log("Constructor")
super(props)
this.state = {
count:0}
}
// 加一 更新状态函数
add = ()=>{
let {
count} = this.state
this.setState({
count:count+1})
}
// 卸载组件函数
death = ()=>{
console.log("卸载完成")
ReactDOM.unmountComponentAtNode(document.getElementById("test"))
}
// 强制更新
force = ()=>{
console.log("强制更新")
this.forceUpdate()
}
// 组件将要挂载
componentWillMount(){
console.log("componentWillMount")
}
// 组件挂载完成
componentDidMount(){
console.log("componentDidMount")
}
// 组件将要卸载
componentWillUnmount(){
console.log("componentWillUnmount")
}
// 控制组件更新的阀门
shouldComponentUpdate(){
console.log("shouldComponentUpdate")
// 必须返回布尔类型 false则无法进行更新
return false
}
// 组件将要更新
componentWillUpdate(){
console.log("componentWillUpdate")
}
render(){
console.log("render")
let {
count} = this.state
return(
<div>
<h2>当前数字为{
count}</h2>
<button type="button" onClick={
this.add}>点我+1</button>
<button type="button" onClick={
this.death}>卸载组件</button>
<button onClick={
this.force}>强制更新</button>
</div>
)
}
}
ReactDOM.render(<Count/>,document.getElementById("test"))
父子组件
- 父子组件的简单使用
class A extends React.Component{
render(){
return (
<div>
我是A组件
<B/>
</div>
)
}
}
class B extends React.Component{
render(){
return (
<div>我是B组件</div>
)
}
}
ReactDOM.render(<A/>,document.getElementById("test"))
- 父子组件间传值
class A extends React.Component{
state = {
carName:"奔驰"}
changeCar = ()=>{
this.setState({
carName:"宝马"
})
}
render(){
return (
<div>
我是A组件
<button onClick={
this.changeCar}>换车</button>
<B carName={
this.state.carName}/>
</div>
)
}
}
class B extends React.Component{
render(){
return (
<div>B组件接收到的车名是:{
this.props.carName}</div>
)
}
}
ReactDOM.render(<A/>,document.getElementById("test"))
总结
-
初始化阶段:由ReactDOM.render()触发----初次渲染
- constructor()
- componentWillMount()
- render()
- componentDidMount()
-
更新阶段:由组件内部this.setState()或父组件render触发
- shouldComponentUpdate()
- componentWillUpdate()
- render()
- componentDidUpdate()
-
卸载组件:由ReactDOM.unmountComponentAtNode()触发
- componentWillUnmount()
卸载组件函数:ReactDOM.unmountComponentAtNode()
生命周期(新)
static getDerivedStateFromProps()
会在调用render方法之前调用,并且在初始挂载及后续更新时,如果返回null则不更新任何内容。从props中得到一个派生的状态,适用于state的值在任何时候都取决于props
static getSnapshotBeforeUpdate()
在最近一次渲染输出(提交到DOM节点)之前调用。它使得组件能在发生更改之前从DOM中捕获一些信息。此生命周期的任何返回值将作为参数传递给componentDidUpdate
总结
-
初始化阶段:由ReactDOM.render() —初次渲染
- constructor()
- getDerivedStateFromProps
- render()
- componentDidMount()
-
更新阶段:由组件内部this.setState()或父组件重新render触发
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
-
卸载组件:由ReactDOM.unmountComponentAtNode触发
- componentWillUnmount
React中的Key
React中的key有什么作用?
- key是虚拟dom对象的标识,在更新显示时key起着非常重要的作用
- diffing比较规则:
-
旧虚拟DOM中找到了与新虚拟DOM相同的KEY
- 若虚拟DOM中内容没变,直接使用之前的真实DOM
- 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换页面中之前的真实DOM
-
旧虚拟DOM中未找到与新虚拟DOM相同的KEY:根据数据创建新的真实DOM,随后渲染到页面
为什么遍历的时候key最好不要用index?
- 若对数据进行:逆序添加,逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新
- 如果结构中还包含输入类的DOM,会产生错误DOM更新