您现在的位置是:首页 > 编程语言学习 > 后端编程语言 > 文章正文 后端编程语言

JavaScript使用useEffect模拟组件生命周期

2022-09-15 09:58:01 后端编程语言

简介useEffect模拟组件生命周期让函数组件模拟生命周期默认函数组件没有生命周期函数组件是一个纯函数,执行完即销毁,自己无法实现生命周期通

useEffect模拟组件生命周期

让函数组件模拟生命周期

默认函数组件没有生命周期函数组件是一个纯函数,执行完即销毁,自己无法实现生命周期通过Effect hook把生命周期“钩”到纯函数中
  1. // 模拟 class 组件的 DidMount 和 DidUpdate 
  2. useEffect(() => { 
  3.   console.log('在此发送一个 ajax 请求'
  4. }) 
  5.  
  6. // // 模拟 class 组件的 DidMount 
  7.  useEffect(() => { 
  8.     console.log('加载完了'
  9.  }, []) // 第二个参数是 [] (不依赖于任何 state) 
  10.  
  11.  // 模拟 class 组件的 DidUpdate 
  12.  useEffect(() => { 
  13.      console.log('更新了'
  14.  }, [count, name]) // 第二个参数就是依赖的 state 
  15.  
  16. // 模拟 class 组件的 DidMount 
  17. useEffect(() => { 
  18.     let timerId = window.setInterval(() => { 
  19.         console.log(Date.now()) 
  20.     }, 1000) 
  21.  
  22.     // 返回一个函数 
  23.     // 模拟 WillUnMount 组件销毁的时候 停止计时器 
  24.     return () => { 
  25.         window.clearInterval(timerId) 
  26.     } 
  27. }, []) 

总结:

模拟componentDidMount - useEffect 依赖 [ ]模拟compenentDidUpdate - useEffect 无依赖 ,或者 依赖 [a,b,c]模拟componentWillUnMount - useEffect 中返回一个函数

react在16.8之后有了新特性 react hooks

之前的主要的生命周期为:

初始化

在组件初始化阶段会执行

  1. constructorcomponentWillMount()render()componentDidMount() 

更新阶段

props或state的改变可能会引起组件的更新,组件重新渲染的过程中会调用以下方法:

  1. componentWillReceiveProps()shouldComponentUpdate()componentWillUpdate()render()componentDidUpdate() 

卸载阶段

  1. componentWillUnmount() 

useEffect实现componentWillUnmount生命周期函数

阐述

在写React应用的时候,在组件中经常用到 componentWillUnmount 生命周期函数(组件将要被卸载时执行)。比如我们的定时器要清空,避免发生内存泄漏;比如登录状态要取消掉,避免下次进入信息出错。

所以这个生命周期函数也是必不可少的,本文就用 useEffect 来实现这个生命周期函数,并讲解一下 useEffect 容易踩的坑。

useEffect 解绑副作用

学习React Hooks 时,我们要改掉生命周期函数的概念,因为Hooks叫它副作用,所以componentWillUnmount也可以理解成解绑副作用。

这里为了演示用useEffect来实现类似componentWillUnmount效果,先安装React-Router路由,进入项目根本录,使用npm进行安装。


  1. npm install --save react-router-dom@5.2.0 

然后打开 Example.js 文件,进行改写代码,先引入对应的React-Router组件。


  1. import { BrowserRouter as Router, Route, Link } from "react-router-dom" 

在文件中编写两个新组件,因为这两个组件都非常的简单,所以就不单独建立一个新的文件来写了。

  1. function Index() { 
  2. return 

    willem

  3. function List() { 
  4. return 

    List-Page

有了这两个组件后,接下来可以编写路由配置,在以前的计数器代码中直接增加就可以了。

  1. function Example(){ 
  2. const [count, setCount] = useState(0); 
  3. return (  
  4.  
  5. You clicked {count} times

     
  6. {setCount(count + 1)}}>Chlick me 
  7.  
    •  
      •  
      • "/">首页 
      •  
        •  
        • "/list/">列表 
        •  
          •  
           
        • "/" exact component={Index} /> 
        • "/list/" component={List} /> 
        •  
        •  
        • ); 

然后到浏览器中查看一下,看看组件和路由是否可用。

如果可用,我们现在可以调整useEffect了。

在两个新组件中分别加入useEffect()函数:

  1. function Index() { 
  2. useEffect(()=>{ 
  3. console.log('useEffect=>我是 Index页面'
  4. }) 
  5. return 

    willem

  6. function List() { 
  7. useEffect(()=>{ 
  8. console.log('useEffect=>我是 List页面'
  9. }) 
  10. return 

    List-Page

这时候我们点击Link进入任何一个组件,在浏览器中都会打印出对应的一段话。这时候可以用返回一个函数的形式进行解绑,代码如下:

  1. function Index() { 
  2. useEffect(()=>{ 
  3. console.log('useEffect=>我是Index页面'
  4. return ()=>{ 
  5. console.log('你走了 Index页面'
  6. }) 
  7. return 

    willem

这时候你在浏览器中预览,我们仿佛实现了 componentWillUnmount方法。

但这只是好像实现了,当点击计数器按钮时,你会发现你走了Index页面,也出现了。

这到底是怎么回事那?

其实每次状态发生变化,useEffect都进行了解绑。

ReactHooksDemo\demo01\src\Example.js

  1. import React, { useState, useEffect } from 'react'
  2. import { BrowserRouter as Router, Route, Link } from "react-router-dom" 
  3. function Index() { 
  4. useEffect(()=>{ 
  5. console.log('useEffect=>我是Index页面'
  6. return ()=>{ 
  7. console.log('你走了 Index页面'
  8. },[]) 
  9. return 

    willem

  10. function List() { 
  11. useEffect(()=>{ 
  12. console.log('useEffect=>我是 List页面'
  13. }) 
  14. return 

    List-Page

  15. function Example(){ 
  16. const [count, setCount] = useState(0); 
  17. return (  
  18.  
  19. You clicked {count} times

     
  20. {setCount(count + 1)}}>Chlick me 
  21.  
    •  
      •  
      • "/">首页 
      •  
        •  
        • "/list/">列表 
        •  
          •  
           
        • "/" exact component={Index} /> 
        • "/list/" component={List} /> 
        •  
        •  
        • ); 
        • export default Example; 

useEffect的第二个参数

那到底要如何实现类似 componentWillUnmount的效果那?

这就需要请出useEffect的第二个参数,它是一个数组,数组中可以写入很多状态对应的变量,意思是当状态值发生变化时,我们才进行解绑。

但是当传空数组 [] 时,就是当组件将被销毁时才进行解绑,这也就实现了componentWillUnmount的生命周期函数。

  1. function Index() { 
  2. useEffect(()=>{ 
  3. console.log('useEffect=>我是Index页面'
  4. return ()=>{ 
  5. console.log('你走了 Index页面'
  6. },[]) 
  7. return 

    willem

为了更加深入了解第二个参数的作用,把计数器的代码也加上 useEffect 和解绑方法,并加入第二个参数为空数组。

代码如下:

ReactHooksDemo\demo01\src\Example.js

  1. function Example(){ 
  2. const [count, setCount] = useState(0); 
  3. useEffect(()=>{ 
  4. console.log(`useEffect=>You clicked ${count} times`) 
  5. return ()=>{ 
  6. console.log('===================='
  7. },[]) 
  8. return (  
  9.  
  10. You clicked {count} times

     
  11. {setCount(count + 1)}}>Chlick me 
  12.  
    •  
      •  
      • "/">首页 
      •  
        •  
        • "/list/">列表 
        •  
          •  
           
        • "/" exact component={Index} /> 
        • "/list/" component={List} /> 
        •  
        •  
        • ); 

这时候的代码是不能执行解绑副作用函数的。

但是如果我们想每次count发生变化,我们都进行解绑,只需要在第二个参数的数组里加入count变量就可以了。

代码如下:

  1. function Example(){ 
  2. const [count, setCount] = useState(0); 
  3. useEffect(()=>{ 
  4. console.log(`useEffect=>You clicked ${count} times`) 
  5. return ()=>{ 
  6. console.log('===================='
  7. },[count]) 
  8. return (  
  9.  
  10. You clicked {count} times

     
  11. {setCount(count + 1)}}>Chlick me 
  12.  
    •  
      •  
      • "/">首页 
      •  
        •  
        • "/list/">列表 
        •  
          •  
           
        • "/" exact component={Index} /> 
        • "/list/" component={List} /> 
        •  
        •  
        • ); 

这时候只要count状态发生变化,都会执行解绑副作用函数,浏览器的控制台也就打印出了一串=================。

总结

通过对本文的学习,让我们对useEffect函数有了一个比较深入的了解,并且可以通过useEffect实现生命周期函数了,现在用React Hooks这种函数的方法编写组件,对比以前用Class编写组件几乎一样了。

ReactHooksDemo\demo01\src\index.js

  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import Example from './Example'
  4. ReactDOM.render(, document.getElementById('root')); 

ReactHooksDemo\demo01\src\Example.js

  1. import React, { useState, useEffect } from 'react'
  2. import { BrowserRouter as Router, Route, Link } from "react-router-dom" 
  3. function Index() { 
  4. useEffect(()=>{ 
  5. console.log('useEffect=>我是Index页面'
  6. return ()=>{ 
  7. console.log('你走了 Index页面'
  8. },[]) 
  9. return 

    willem

  10. function List() { 
  11. useEffect(()=>{ 
  12. console.log('useEffect=>我是 List页面'
  13. }) 
  14. return 

    List-Page

  15. function Example(){ 
  16. const [count, setCount] = useState(0); 
  17. useEffect(()=>{ 
  18. console.log(`useEffect=>You clicked ${count} times`) 
  19. return ()=>{ 
  20. console.log('===================='
  21. },[count]) 
  22. return (  
  23.  
  24. You clicked {count} times

     
  25. {setCount(count + 1)}}>Chlick me 
  26.  
    •  
      •  
      • "/">首页 
      •  
        •  
        • "/list/">列表 
        •  
          •  
           
        • "/" exact component={Index} /> 
        • "/list/" component={List} /> 
        •  
        •  
        • ); 
        • export default Example; 

 

相关文章

站点信息