4.React生命週期

4.1引出生命週期

  1. class Life extends React.Component {
  2. state = {
  3. opacity:0.5
  4. }
  5. death = () => {
  6. // 解除安裝定時器
  7. // clearInterval(this.timer)
  8. // 解除安裝元件
  9. ReactDOM.unmountComponentAtNode(document.getElementById('test'))
  10. }
  11. // 生命週期鉤子函式
  12. // 元件掛載完呼叫
  13. componentDidMount(){
  14. this.timer = setInterval(()=>{
  15. // 獲取原狀態
  16. let {opacity} = this.state
  17. // 減小0.1
  18. opacity -= 0.1
  19. // 設定新的透明度
  20. if (opacity <= 0) opacity = 1
  21. this.setState({opacity})
  22. }, 200)
  23. }
  24. // 元件將要解除安裝操作
  25. componentWillUnmount(){
  26. // 解除安裝定時器
  27. clearInterval(this.timer)
  28. }
  29. render(){
  30. return (
  31. <div>
  32. <h2 style={{opacity: this.state.opacity}}>yeyang is da hanbi</h2>
  33. <button onClick={this.death}>don't life</button>
  34. </div>
  35. )
  36. }
  37. }

4.2 react生命週期(舊)(17.0版本之前)

  1. /*
  2. 1. 初始化階段: 由ReactDOM.render()觸發---初次渲染
  3. 1. constructor()
  4. 2. componentWillMount()
  5. 3. render()
  6. 4. componentDidMount() ====> 常用
  7. --- 一般在這個鉤子做一些初始化的事,例如:開啟定時器,傳送網路請求,訂閱訊息
  8. 2. 更新階段: 由元件內部this.setSate()或父元件重新render觸發
  9. 1. shouldComponentUpdate()
  10. 2. componentWillUpdate()
  11. 3. render() ====> 必須使用的一個
  12. 4. componentDidUpdate()
  13. 3. 解除安裝元件: 由ReactDOM.unmountComponentAtNode()觸發
  14. 1. componentWillUnmount() ====> 常用
  15. ---- 一般在這個鉤子中做一些收尾的事,如關閉定時器、取消訂閱訊息
  16. */
  17. class Count extends React.Component {
  18. constructor(props) {
  19. console.log('Count---constructor')
  20. super(props);
  21. this.state = {
  22. count: 0
  23. }
  24. }
  25. // state = {
  26. // count: 0
  27. // }
  28. add = () => {
  29. const {count} = this.state
  30. this.setState({
  31. count: count+1
  32. })
  33. }
  34. death = () => {
  35. ReactDOM.unmountComponentAtNode(document.getElementById('test'))
  36. }
  37. force = () => {
  38. this.forceUpdate() // 強制更新鉤子
  39. }
  40. // 元件將要掛載的鉤子
  41. componentWillMount(){
  42. console.log('Count---componentWillMount')
  43. }
  44. // 元件掛載完成的鉤子
  45. componentDidMount(){
  46. console.log('Count---componentDidMount')
  47. }
  48. // 元件將要解除安裝時的鉤子
  49. componentWillUnmount(){
  50. console.log('Count---componentWillUnmount')
  51. }
  52. // 控制組件更新的閥門: 是否更新元件鉤子
  53. shouldComponentUpdate(){
  54. console.log('Count---shouldComponentUpdate')
  55. return true
  56. }
  57. // 元件將要更新的鉤子
  58. componentWillUpdate(){
  59. console.log('Count---componentWillUpdate')
  60. }
  61. // 元件更新完的鉤子
  62. componentDidUpdate(){
  63. console.log('Count---componentDidUpdate')
  64. }
  65. render(){
  66. console.log('Count---render')
  67. const {count} = this.state
  68. return (
  69. <div>
  70. <h2> 當前求和為{count}</h2>
  71. <button onClick={this.add}>點我+1</button>
  72. <button onClick={this.death}>解除安裝元件</button>
  73. <button onClick={this.force}>強制更新</button>
  74. </div>
  75. )
  76. }
  77. }
  78. // 父元件A
  79. class A extends React.Component{
  80. state = {
  81. carName: 'benz'
  82. }
  83. changeCar = () => {
  84. this.setState({
  85. carName: 'bmw'
  86. })
  87. }
  88. render(){
  89. return (
  90. <div>
  91. <div>我是A元件</div>
  92. <button onClick={this.changeCar}>換車</button>
  93. <B carName={this.state.carName}/>
  94. </div>
  95. )
  96. }
  97. }
  98. // 子元件B
  99. class B extends React.Component{
  100. // 元件將要接收新的props的鉤子
  101. componentWillReceiveProps(props){
  102. console.log('B---componentWillReceiveProps', props)
  103. }
  104. shouldComponentUpdate(){
  105. console.log('B---shouldComponentUpdate')
  106. return true
  107. }
  108. // 元件將要更新的鉤子
  109. componentWillUpdate(){
  110. console.log('B---componentWillUpdate')
  111. }
  112. // 元件更新完的鉤子
  113. componentDidUpdate(){
  114. console.log('B---componentDidUpdate')
  115. }
  116. render(){
  117. return (
  118. <div>
  119. 我是B元件, 接收的車是:{this.props.carName}
  120. </div>
  121. )
  122. }
  123. }
  124. // ReactDOM.render(<Count />, document.getElementById('test'))
  125. ReactDOM.render(<A />, document.getElementById('test'))

4.3 react生命週期(新)(17.0版本之後)

  1. /*
  2. 1. 初始化階段: 由ReactDOM.render()觸發---初次渲染
  3. 1. constructor()
  4. 2. getDerivedStateFromProps
  5. 3. render()
  6. 4. componentDidMount()
  7. 2. 更新階段: 由元件內部this.setSate()或父元件重新render觸發
  8. 1. getDerivedStateFromProps
  9. 2. shouldComponentUpdate()
  10. 3. render()
  11. 4. getSnapshotBeforeUpdate
  12. 5. componentDidUpdate()
  13. 3. 解除安裝元件: 由ReactDOM.unmountComponentAtNode()觸發
  14. 1. componentWillUnmount()
  15. */
  16. class Count extends React.Component {
  17. constructor(props) {
  18. console.log('Count---constructor')
  19. super(props);
  20. this.state = {
  21. count: 0
  22. }
  23. }
  24. // state = {
  25. // count: 0
  26. // }
  27. add = () => {
  28. const {count} = this.state
  29. this.setState({
  30. count: count+1
  31. })
  32. }
  33. death = () => {
  34. ReactDOM.unmountComponentAtNode(document.getElementById('test'))
  35. }
  36. force = () => {
  37. this.forceUpdate() // 強制更新鉤子
  38. }
  39. // 若state的值在任何時候都取決於props,可以使用該方法
  40. static getDerivedStateFromProps(props ,state){
  41. console.log('Count---getDerivedStateFromProps', props, state)
  42. return null // 返回 state物件或者null
  43. }
  44. // 在更新之前獲取快照
  45. getSnapshotBeforeUpdate(){
  46. console.log('Count---getSnapshotBeforeUpdate')
  47. return 'abc'
  48. }
  49. // 元件掛載完成的鉤子
  50. componentDidMount(){
  51. console.log('Count---componentDidMount')
  52. }
  53. // 元件將要解除安裝時的鉤子
  54. componentWillUnmount(){
  55. console.log('Count---componentWillUnmount')
  56. }
  57. // 控制組件更新的閥門: 是否更新元件鉤子
  58. shouldComponentUpdate(){
  59. console.log('Count---shouldComponentUpdate')
  60. return true
  61. }
  62. // 元件更新完的鉤子
  63. componentDidUpdate(preProps, preState, snapshotValue){
  64. console.log('Count---componentDidUpdate', preProps, preState, snapshotValue)
  65. }
  66. render(){
  67. console.log('Count---render')
  68. const {count} = this.state
  69. return (
  70. <div>
  71. <h2> 當前求和為{count}</h2>
  72. <button onClick={this.add}>點我+1</button>
  73. <button onClick={this.death}>解除安裝元件</button>
  74. <button onClick={this.force}>強制更新</button>
  75. </div>
  76. )
  77. }
  78. }
  79. ReactDOM.render(<Count count={199}/>, document.getElementById('test'))

4.4 getSnapshotBeforeUpdate使用場景

拖動滾動條讓滾動條停留在當前資料位置

  1. class NewList extends React.Component {
  2. state = {
  3. newsArr: []
  4. }
  5. componentDidMount() {
  6. setInterval(() => {
  7. // 獲取原狀態
  8. const {newsArr} = this.state
  9. // 模擬一條新聞
  10. const news = '新聞' + (newsArr.length + 1)
  11. // 更新狀態
  12. this.setState({
  13. newsArr: [news, ...newsArr]
  14. })
  15. }, 1000)
  16. }
  17. getSnapshotBeforeUpdate() {
  18. return this.refs.list.scrollHeight
  19. }
  20. componentDidUpdate(preProps, preState, height) {
  21. console.log(preProps, preState, height)
  22. console.log(this.refs.list.scrollTop) // 當前距離滾動條頂端的距離
  23. this.refs.list.scrollTop += (this.refs.list.scrollHeight - height)
  24. // this.refs.list.scrollTop += 30
  25. }
  26. render() {
  27. console.log('NewList---render')
  28. const {newsArr} = this.state
  29. return (
  30. <div className="list" ref='list'>
  31. {
  32. newsArr.map((n, index) => {
  33. return <div key={index} className="news">{n}</div>
  34. })
  35. }
  36. </div>
  37. )
  38. }
  39. }
  40. ReactDOM.render(<NewList/>, document.getElementById('test'))