react初学day03
生命周期
<script src="./base/react.min.js"></script>
<script src="./base/react-dom.min.js"></script>
<script src="./base/browser.min.js"></script>
//和昨天一样的js文件
初始化生命周期钩子函数
1.getDefaultProps
初始化默认值
2.getInititalState
初始化状态
3.componentWillMount
可以做一些初始化的设置 获取一些数据,但是不建议在这里使用下面细说
4.render
渲染真实dom
5.componentDidMount
渲染真实dom之后
<body>
<div id="app"></div>
<div id="app1"></div>
<script type="text/babel">
var props_num = 0;
var state_num = 0;
var Hello = React.createClass({
getDefaultProps(){ //初始化值,实例化时,第一个执行,但是实例化多次,只执行一遍
console.log("getDefaultProps...")
return {
num:++props_num
}
},
//作用:设置组件的初始化状态
//特点:为每一个组件设置新的状态 简言之,实例化几次,就执行几次
getInitialState(){
console.log("getInitialState...")
return {
num:++state_num
}
},
//作用:在这里获取组件的属性与状态,并且可以更改状态
//在这里更改状态不会影响运行时钩子函数的执行
//功能?可以做一些初始化的设置 获取一些数据(ajax)
//但是不在这里进行数据请求。
//1. 首先未来的17的版本废弃 2.16版,fiber算法 这个钩子函数可能会执行多次,
//这就意味着,ajax请求也会有多次,这显然不符合我们的预期所以在componentDidMount中请求数据
//类似于vue中created+beforeMount的结合体
componentWillMount(){
console.log("componentWillMount...")
},
render(){ //渲染真实dom
console.log("render...")
return (
<div>hello! {this.props.num} {this.state.num}</div>
)
},
//建议将数据请求的代码放在此钩子函数里面
//可以操作真实dom 并且可以实例化一些插件 (类似于vue中mounted)
componentDidMount(){
console.log("componentDidmount...")
}
})
ReactDOM.render(<Hello/>,app)
ReactDOM.render(<Hello/>,app1)
//实例化两次,运行结果看截图
</script>
</body>
显而易见:实例化两次,
getDefaultProps运行一遍
getInitialState
componentWillMount
render
componentDidmount
这四个函数运行两遍,且按顺序执行
运行中钩子函数
1.componentWillReceiveProps
即将接收数据
2.shouldComponentUpdate
属性或者状态改变的时候,此钩子函数就会执行
3.componentWillUpdate
shouldComponentUpdate一旦返回true,这个函数立马触发
4.componentDidUpdate
render渲染完毕后触发
一个简单的实例,爸爸打儿子,打五次儿子会疼
<body>
<div id="app"></div>
<script type="text/babel">
var Father = React.createClass({
getInitialState(){ //初始化状态
return {
hit:0
}
},
hitSon(){
//更改自身状态
this.setState({
hit:++this.state.hit
})
},
render(){
return (
<div>
<p>我是father..</p>
<p><button onClick={this.hitSon}>开打了!</button></p>
<Son hitnum={this.state.hit}/> //将次数传递给儿子
</div>
)
}
});
var Son = React.createClass({
getInitialState(){ //初始化状态,不疼
return {
pain:false
}
},
//此钩子函数默认不会执行,只有属性发生改变的时候,才会执行此钩子函数
//会发现this.props.hitnum获取到的还是之前的属性
//作用?可以根据更改后的属性做一些操作,例如可以更改状态
//并且在这里更改状态不会触发生命周期钩子函数的重复执行
componentWillReceiveProps(nextProps,nextState){
//两个参数,第一个是更新后的参数,第二个是更新后的状态
console.log("componentWillReceiveProps....",nextProps.hitnum)
if(nextProps.hitnum >=5 && !this.state.pain){
this.setState({pain:true})
}
},
//触发条件:属性或者状态改变的时候,此钩子函数就会执行
//默认返回true 向下执行组件更新操作 返回false就不会执行更新操作了
//作用? 可以阻止组件的更新,提升性能,很重要
shouldComponentUpdate(nextProps,nextState){
console.log("shouldComponentUpdate...")
if(nextProps.hitnum>=5){ //如果打了5次,才会进行后续的更新组件 虚拟dom对比
return true;
}
return false //后续更新操作不再执行了!
},
//触发条件: shouldComponentUpdate一旦返回true立马触发
componentWillUpdate(){
console.log("componentWillUpdate...")
},
render(){
console.log("render...")
let {pain} = this.state;
return (
<div>
<p>我是son </p>
<p>被打了{this.props.hitnum}次</p>
<p>我{pain || "不"}疼</p>
</div>
)
},
componentDidUpdate(){
console.log("componentDidUpdate...")
},
})
ReactDOM.render(<Father/>,app)
</script>
</body>
①运行完截图,页面会进行一次渲染
②开打第一次截图,接收到数据了,执行shouldComponentUpdate,但是不符合我们的条件,所以返回false不执行页面渲染等三个钩子函数。可见我们的值已经被修改了,但是页面上没有显示
③开打第二次
④开打第五次,依旧接收了数据,数据改变执行shouldComponentUpdate,这次返回true,开始执行componentWillUpdate,然后渲染页面render,渲染完毕componentDidUpdate。我们在shouldComponentUpdate中进行判断,只有符合条件了才会进行dom操作,所以可以在这里进行优化处理
完美的符合我们的生命周期图示
销毁时触发的钩子函数
componentWillUnmount
<style>
body { height: 2000px; }
#app { position: fixed; }
.world { width: 100px; height: 100px; border: 1px solid red; }
</style>
<body>
<div id="app"></div>
</body>//这个实例,每次点击的时候,让元素显示与隐藏
<script type = "text/babel">
var Hello = React.createClass({
getInitialState(){ //初始化我们的状态
return {
isShow:true
}
},
toggle(){ //这是个开关,每次点击我们改变isShow的状态
this.setState((prevState,prevProps)=>{
return {
isShow:!prevState.isShow
}
})
},
render(){
return (
<div>
<button onClick={this.toggle}>toggle</button>
{!this.state.isShow || <World/>}
</div>
)
}
})
var World = React.createClass({
//当组件销毁的时候,执行componentWillUnmount
//销毁的钩子函数? 可以做一些善后的操作 清除定时器 清除事件绑定
componentWillUnmount(){
console.log("world-componentWillUnmount")
clearInterval(this.timer);
},
componentWillMount(){
//开启定时器
this.timer = setInterval(() => {
console.log(11111111111111)
this.changeColor()
}, 1000);
},
changeColor(){ //状态只能自身去改变
this.setState({
color: this.getRandomColor()
})
},
getInitialState(){ //初始化我们的颜色状态
return {
color:"blue"
}
},
render(){
return (
<div style={{background:this.state.color}} className="world"></div>
)
},
getRandomColor () { //这是个生成随机颜色的方法
return '#'+'0123456789abcdef'.split('').map(function(v,i,a){
return i>5 ? null : a[Math.floor(Math.random()*16)] }).join('');
}
})
ReactDOM.render(<Hello/>,document.getElementById('app'))
</script>
①这里运行之后,下面的div框的背景颜色会一秒一变,我们在定时器中,改变状态,改变状态之后,会触发shouldComponentUpdate钩子函数,默认返回值为true,然后执行componentWillUpdate,紧接着render渲染页面,再然后执行componentDidUpdate,所以页面上的元素在,在状态改变时,也会实时更新。(根据最上面的图示也可以看到)
②然后我们点击toggle按钮,让isShow变为非isShow,可见触发了我们的componentWillUnmount钩子函数。
这里加点别的,vue框架在销毁组件的时候,只是解除数据的双向绑定、监听等,且dom结构还存在,而react是将dom也消除掉。
这里总结一下,不管是属性还是状态改变,render函数会重新执行,页面都会重新渲染
这里shouldComponentUpdate 默认返回true
属性改变 componentWillReceiveProps—> shouldComponentUpdate—> componentWillUpdate—> render—> componentDidUpdate
状态改变 shouldComponentUpdate—> componentWillUpdate—> render—> componentDidUpdate