4.React生命週期
4.1引出生命週期
class Life extends React.Component {
state = {
opacity:0.5
}
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(){
return (
<div>
<h2 style={{opacity: this.state.opacity}}>yeyang is da hanbi</h2>
<button onClick={this.death}>don't life</button>
</div>
)
}
}
4.2 react生命週期(舊)(17.0版本之前)
/*
1. 初始化階段: 由ReactDOM.render()觸發---初次渲染
1. constructor()
2. componentWillMount()
3. render()
4. componentDidMount() ====> 常用
--- 一般在這個鉤子做一些初始化的事,例如:開啟定時器,傳送網路請求,訂閱訊息
2. 更新階段: 由元件內部this.setSate()或父元件重新render觸發
1. shouldComponentUpdate()
2. componentWillUpdate()
3. render() ====> 必須使用的一個
4. componentDidUpdate()
3. 解除安裝元件: 由ReactDOM.unmountComponentAtNode()觸發
1. componentWillUnmount() ====> 常用
---- 一般在這個鉤子中做一些收尾的事,如關閉定時器、取消訂閱訊息
*/
class Count extends React.Component {
constructor(props) {
console.log('Count---constructor')
super(props);
this.state = {
count: 0
}
}
// state = {
// count: 0
// }
add = () => {
const {count} = this.state
this.setState({
count: count+1
})
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
force = () => {
this.forceUpdate() // 強制更新鉤子
}
// 元件將要掛載的鉤子
componentWillMount(){
console.log('Count---componentWillMount')
}
// 元件掛載完成的鉤子
componentDidMount(){
console.log('Count---componentDidMount')
}
// 元件將要解除安裝時的鉤子
componentWillUnmount(){
console.log('Count---componentWillUnmount')
}
// 控制組件更新的閥門: 是否更新元件鉤子
shouldComponentUpdate(){
console.log('Count---shouldComponentUpdate')
return true
}
// 元件將要更新的鉤子
componentWillUpdate(){
console.log('Count---componentWillUpdate')
}
// 元件更新完的鉤子
componentDidUpdate(){
console.log('Count---componentDidUpdate')
}
render(){
console.log('Count---render')
const {count} = this.state
return (
<div>
<h2> 當前求和為{count}</h2>
<button onClick={this.add}>點我+1</button>
<button onClick={this.death}>解除安裝元件</button>
<button onClick={this.force}>強制更新</button>
</div>
)
}
}
// 父元件A
class A extends React.Component{
state = {
carName: 'benz'
}
changeCar = () => {
this.setState({
carName: 'bmw'
})
}
render(){
return (
<div>
<div>我是A元件</div>
<button onClick={this.changeCar}>換車</button>
<B carName={this.state.carName}/>
</div>
)
}
}
// 子元件B
class B extends React.Component{
// 元件將要接收新的props的鉤子
componentWillReceiveProps(props){
console.log('B---componentWillReceiveProps', props)
}
shouldComponentUpdate(){
console.log('B---shouldComponentUpdate')
return true
}
// 元件將要更新的鉤子
componentWillUpdate(){
console.log('B---componentWillUpdate')
}
// 元件更新完的鉤子
componentDidUpdate(){
console.log('B---componentDidUpdate')
}
render(){
return (
<div>
我是B元件, 接收的車是:{this.props.carName}
</div>
)
}
}
// ReactDOM.render(<Count />, document.getElementById('test'))
ReactDOM.render(<A />, document.getElementById('test'))
4.3 react生命週期(新)(17.0版本之後)
/*
1. 初始化階段: 由ReactDOM.render()觸發---初次渲染
1. constructor()
2. getDerivedStateFromProps
3. render()
4. componentDidMount()
2. 更新階段: 由元件內部this.setSate()或父元件重新render觸發
1. getDerivedStateFromProps
2. shouldComponentUpdate()
3. render()
4. getSnapshotBeforeUpdate
5. componentDidUpdate()
3. 解除安裝元件: 由ReactDOM.unmountComponentAtNode()觸發
1. componentWillUnmount()
*/
class Count extends React.Component {
constructor(props) {
console.log('Count---constructor')
super(props);
this.state = {
count: 0
}
}
// state = {
// count: 0
// }
add = () => {
const {count} = this.state
this.setState({
count: count+1
})
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
force = () => {
this.forceUpdate() // 強制更新鉤子
}
// 若state的值在任何時候都取決於props,可以使用該方法
static getDerivedStateFromProps(props ,state){
console.log('Count---getDerivedStateFromProps', props, state)
return null // 返回 state物件或者null
}
// 在更新之前獲取快照
getSnapshotBeforeUpdate(){
console.log('Count---getSnapshotBeforeUpdate')
return 'abc'
}
// 元件掛載完成的鉤子
componentDidMount(){
console.log('Count---componentDidMount')
}
// 元件將要解除安裝時的鉤子
componentWillUnmount(){
console.log('Count---componentWillUnmount')
}
// 控制組件更新的閥門: 是否更新元件鉤子
shouldComponentUpdate(){
console.log('Count---shouldComponentUpdate')
return true
}
// 元件更新完的鉤子
componentDidUpdate(preProps, preState, snapshotValue){
console.log('Count---componentDidUpdate', preProps, preState, snapshotValue)
}
render(){
console.log('Count---render')
const {count} = this.state
return (
<div>
<h2> 當前求和為{count}</h2>
<button onClick={this.add}>點我+1</button>
<button onClick={this.death}>解除安裝元件</button>
<button onClick={this.force}>強制更新</button>
</div>
)
}
}
ReactDOM.render(<Count count={199}/>, document.getElementById('test'))
4.4 getSnapshotBeforeUpdate使用場景
拖動滾動條讓滾動條停留在當前資料位置
class NewList extends React.Component {
state = {
newsArr: []
}
componentDidMount() {
setInterval(() => {
// 獲取原狀態
const {newsArr} = this.state
// 模擬一條新聞
const news = '新聞' + (newsArr.length + 1)
// 更新狀態
this.setState({
newsArr: [news, ...newsArr]
})
}, 1000)
}
getSnapshotBeforeUpdate() {
return this.refs.list.scrollHeight
}
componentDidUpdate(preProps, preState, height) {
console.log(preProps, preState, height)
console.log(this.refs.list.scrollTop) // 當前距離滾動條頂端的距離
this.refs.list.scrollTop += (this.refs.list.scrollHeight - height)
// this.refs.list.scrollTop += 30
}
render() {
console.log('NewList---render')
const {newsArr} = this.state
return (
<div className="list" ref='list'>
{
newsArr.map((n, index) => {
return <div key={index} className="news">{n}</div>
})
}
</div>
)
}
}
ReactDOM.render(<NewList/>, document.getElementById('test'))