1.引入
挂载:mount
卸载:unmount
//卸载组件
death=()=>{
//卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
<script type="text/babel">
//创建组件
class Life extends React.Component{
state={opacity:1}
death=()=>{
// //清除定时器
// clearInterval(this.timer)
//卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
//组件挂载完毕后调用,只调用一次
componentDidMount(){
this.timer=setInterval(()=>{
//获取原状态
let {opacity} = this.state;
//减小0.1
opacity -=0.1
if(opacity <=0){
opacity =1
}
//设置
this.setState({opacity})
},200)
}
//组件将要被卸载
componentWillUnmount(){
clearInterval(this.timer)
}
//render 初始化渲染+更新
render(){
return(
<div>
<h2 style={{opacity:this.state.opacity}}>React学不会怎么办</h2>
<button onClick={this.death}>不会啊</button>
</div>
)
}
}
//渲染组件
ReactDOM.render(<Life /> ,document.getElementById('test'))
</script>
生命周期回调函数/生命周期钩子函数/生命周期函数/生命周期钩子
生命周期(旧)
总结:
生命周期分为三个阶段
1.初始化阶段 React.Render() 触发——初次渲染
(1)constructor()
(2)componentWillMount()–即将废弃
(3)render()
(4)componentDidMount()----常用,一般做初始化的事,例如:开启定时器,订阅消息,发送网络请求
2.更新阶段 组件内部this.setState()或父组件render()触发
(1)shouldComponentUpdate()
(2)componentWillUpdate()–即将废弃
(3)render()
(4)componentDidupdate()
3.卸载阶段 ReactDOM.unmountComponentAtNode触发
(1)componentWillUnmount()—常用,一般做收尾的事,例如:关闭定时器,取消订阅消息
生命周期(新)
区别:新生命周期废弃了3个钩子,新增了2个钩子(几乎不用)getDerivedStateFromProps、getSnapshotBeforeUpdate
1、getDerivedStateFromProps——适用于state在任何时候都取决于props,一般不用
derived(派生的)
<script type="text/babel">
//创建组件
class Count extends React.Component{
constructor(props){
console.log('count-constructor')
super(props)
//初始化状态
this.state={count:0}
}
static getDerivedStateFromProps(props,state){
console.log('count-getDerivedStateFromProps',props,state)
return props
}
render(){
console.log('count-render')
const {count} =this.state
return(
<div>
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
</div>
)
}
}
//渲染组件
ReactDOM.render(<Count count='133'/>,document.getElementById('test'))
</script>
挂载:
2、getSnapshotBeforeUpdate —不常见
Snapshot快照
//更新之前获取快照
getSnapshotBeforeUpdate(){
console.log('getSnapshotBeforeUpdate')
return 'atGuigu'
}
//组件更新完毕
componentDidUpdate(prevProps,prevState,snapshotValue){
console.log('count-componentDidUpdate',prevProps,prevState,snapshotValue)
}
ReactDOM.render(<Count count='133'/>,document.getElementById('test'))
案例:实现列表数自增和滚动到某位置视图不变
<script type="text/babel">
//创建组件
class NewsList extends React.Component{
state={newsArr:[]}
getSnapshotBeforeUpdate(){
return this.refs.list.scrollHeight
}
componentDidUpdate(prevProps,prevState,height){
this.refs.list.scrollTop += this.refs.list.scrollHeight -height
}
componentDidMount(){
setInterval(()=>{
//获取原状态
const {newsArr} = this.state
//模拟一条新闻
const news = '新闻'+(newsArr.length+1)
//更新状态
this.setState({newsArr:[news,...newsArr]})
},1000)
}
render(){
return(
<div className="list" ref="list">
{
this.state.newsArr.map((n,index)=>{
return(<div className="news" key={index}>{n}</div>)
})
}
</div>
)
}
}
//渲染组件
ReactDOM.render(<NewsList />,document.getElementById('test'))
</script>
总结
1.初始化阶段:有React.render()触发——初次渲染
(1)constructor()
(2)getDerivedStateFromProps()
(3)render()
(4)componentDidmount() ——常用 开启监听,发送ajax请求
2.更新阶段 组件内部this.setState()或父组件render()触发
(1)getDerivedStateFromProps()
(2)shouldComponentUpdate()
(3)render()
(4)getSnapshotBeforeUpdate()
(5)componentDidupdate()
3.卸载阶段 ReactDOM.unmountComponentAtNode触发
(1)componentWillUnmount()——常用 收尾
diffing算法
react/vue的key有什么作用,内部原理是什么?/为什么遍历列表时,key最好不用index?
解答:key是虚拟DOM对象的标识,在更新显示时起着极其重要的作用
1、当状态中的数据发生改变时,react会根据新数据生成新的虚拟DOM,
随后react进行新和旧虚拟DOM的diff比较,规则如下:
(1)若虚拟DOM中找到了和虚拟DOM相同的key:
Ⅰ.若虚拟DOM中内容没变,直接使用之前的真实DOM;
Ⅱ.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换到页面中之前的真实DOM
(2)若旧虚拟DOM中未找到与新虚拟DOM相同的key:
根据数据创建新的真实DOM,随后放在页面
2、用index作为key可能引发的问题:
(1)对数据进行:逆序增加、删除等改变顺序的操作;==》效率低
(2)页面有输入类DOM:会产生错误DOM更新; =》界面有问题
仅用于列表展示,是没有问题的
3、开发中如何选择key?
(1)有唯一标识,则用唯一标识
(2)仅仅简单展示列表
举例:
<script type="text/babel">
class Person extends React.Component{
state={
persons:[
{id:'1',name:'小张',age:18},
{id:'2',name:'小李',age:19},
]
}
add=()=>{
const {persons} = this.state;
const p = {id:persons.length+1,name:'小王',age:20}
this.setState({persons:[p,...persons]})
}
render(){
return (
<div>
<h2>展示人员信息</h2>
<button onClick={this.add}>添加一个小王</button>
<h3>index索引值作为key</h3>
<ul>
{
this.state.persons.map((personObj,index)=>{
return <li key={index}>{personObj.name}---{personObj.age} <input type="text"/></li>
})
}
</ul>
<hr />
<h3>id作为key</h3>
<ul>
{
this.state.persons.map((personObj)=>{
return <li key={personObj.id}>{personObj.name}---{personObj.age} <input type="text"/></li>
})
}
</ul>
</div>
)
}
}
ReactDOM.render(<Person/>,document.getElementById('test'))
</script>