【Vue3从零开始-第二章】2-2 生命周期函数

491 阅读6分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

前言

上一篇文章中,讲过了vue应用的基础概念,今天我们要更深入的了解一下vue了。之前的文章中,也大致用过和了解过部分生命周期函数,在今天的文章中,将会带大家了解vue所有的生命周期函数。

什么是生命周期函数?

  • 在某一时刻会自动执行的函数

触发函数

在之前的代码中,我们会在元素上用v-on:click绑定一个点击事件,当我们点击元素之后就会触发方法中的逻辑。

<script>
    Vue.createApp({
        data(){
            return {
                message: 'Hello World'
            }
        },
        methods: {
            handleClick(){
                alert('点击触发')
            }
        },
        template: "<div v-on:click='handleClick'>{{message}}</div>"
    }).mount('#root');
</script>

k89vl-bu7wq.gif

通过上面的代码可以看出,点击事件触发时,是调用的methods里面的函数,下面我们就用mounted函数来简单介绍一下这两者的区别。

<script>
    Vue.createApp({
        data(){
            return {
                message: 'Hello World'
            }
        },
        mounted(){
            alert('mounted函数')
        },
        methods: {
            handleClick(){
                alert('点击触发')
            }
        },
        template: "<div v-on:click='handleClick'>{{message}}</div>"
    }).mount('#root');
</script>

emby1-jk3z8.gif

通过刷新浏览器,我们会发现页面中的元素还没加载出来的时候,就自动执行了mounted函数,而且mounted函数是和methods同级的,并不是像其他函数一样包含在methods中的。

生命周期详解

lifecycle.svg

此处是生命周期详解的通用代码,下面的生命周期函数或者相关代码都会在此基础上增改。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    Vue.createApp({
        data(){
            return {
                message: 'Hello World'
            }
        },
        // 此处开始写生命周期函数
        
        // 此处是模板
        template: "<div>{{message}}</div>"
    }).mount('#root');
</script>
</html>

首先我们看到的就是创建一个vue实例,紧接着就开始执行vue里面的逻辑了。

  • 第一步:初始化vue代码,分析vue代码是否有一些事件的绑定(如:v-on)或者是上面提到的生命周期函数(如:mounted

  • 第二步:执行vue中的第一个生命周期函数beforeCreate

    • beforeCreate:在实例生成之前会自动执行的函数

      • 在代码模板中,写下beforeCreate函数,打开浏览器看看执行效果
      beforeCreate(){
         console.log('beforeCreate函数')
      },
      

      image.png

  • 第三步:继续对vue进行初始化,开始分析代码中数据和模板的绑定相关的内容。

  • 第四步:执行vue中的第二个生命周期函数created

    • created:在实例生成之后会自动执行的函数

      • 在执行完beforeCreate函数之后,会紧接着执行created函数
      created(){
         console.log('created函数')
      },
      

      image.png

  • 第五步:判断代码中是否有template选项,有则走左侧的yes,无则走右侧的no

  • 第六步:为yes的时候,vue会将template转为一个render函数,变为函数之后,会将数据和这个函数结合,才能把最终的内容渲染出来。

  • 第七步:执行vue中的第三个生命周期函数beforeMount

    • beforeMount:在组件内容被渲染到页面之前自动执行的函数

      • template转为render函数之后,就会执行beforeMount函数
      beforeMount(){
         console.log('beforeMount函数')
      },
      

      image.png

  • 第八步:用生命周期的函数对数据进行一个结合,生成我们最终想要的一个新的DOM,然后用新的DOM去替换掉body中和vue实例相匹配的DOM(在之前的代码中,是替换掉id=rootdiv标签),最终页面上展示的就是vue实例想要创建出的内容了。

  • 第九步:当页面挂载完成之后,会执行vue中的第三个生命周期函数mounted

    • mounted:在组件内容被渲染到页面之后自动执行的函数

      • beforeMount执行完成之后,就表示页面已经被渲染出来了,此时就会执行mounted函数
      mounted(){
         console.log('mounted函数')
      },
      

      image.png

beforeMount和mounted对比

代码运行成功之后,只能看到浏览器上打印出来的顺序,但是不知道页面渲染的情况,那么下面我们就一起来对beforeMountmounted两个函数做一个对比。

<body>
    <div id="root"></div>
</body>
  • body里面,是有一个id = root的标签元素
Vue.createApp({
    data(){
        return {
            message: 'Hello World'
        }
    },
    beforeCreate(){
        console.log('beforeCreate函数')
    },
    created(){
        console.log('created函数')
    },
    beforeMount(){
        console.log(document.getElementById('root').innerHTML, 'beforeMount函数')
    },
    mounted(){
        console.log(document.getElementById('root').innerHTML, 'mounted函数')
    },
    template: "<div>{{message}}</div>"
}).mount('#root');
  • beforeMountmounted两个函数里面,我们打印一下root下面的innerHTML内容

image.png

  • 通过打印出来的内容可以看出,页面加载完成之后,但是模板还没生成render函数时,beforeMount函数前面是没有打印出任何数据的。在页面渲染完成之后,mounted函数就会打印出root标签下渲染的内容了。

做完上面九个步骤之后,一个完整的vue页面就被渲染出来了,但是我们看到图中还有其他的四个生命周期函数,这四个生命周期函数并不是主动触发的,而是当你有操作之后才会触发的,下面我们就详细讲解一下这四个生命周期函数吧。

  • beforeUpdate:当data中的数据发生变化时自动执行的函数

    • 首先我们把代码里面的逻辑改造一下,为了后面方便触发函数,并在代码中写上了beforeUpdate函数
    const app = Vue.createApp({
        data(){
            return {
                message: 'Hello World'
            }
        },
        beforeCreate(){
            console.log('beforeCreate函数')
        },
        created(){
            console.log('created函数')
        },
        beforeMount(){
            console.log('beforeMount函数')
        },
        mounted(){
            console.log('mounted函数')
        },
        beforeUpdate(){
            console.log('beforeUpdate函数')
        },
        template: "<div>{{message}}</div>"
    });
    const vm = app.mount('#root');
    

    image.png

但是在浏览器中,并没有看到beforeUpdate被执行,这时候我们应该怎么触发效果呢?

在下图中,我们可以看到用vm.$data改变data里面的数据时,会自动执行beforeUpdate函数,而且是在页面渲染之前触发的。

81m9s-hkhwg.gif

  • updated:当data中的数据发生变化,同时页面完成更新后,会自动执行的函数

    • beforeUpdate的代码基础上,我们加上updated函数
    updated(){
        console.log('updated函数')
    },
    

    image.png

此时打开浏览器更新的时候,发现并没有很直观的感受,那么我们就对这两个函数做一个对比看看。

beforeUpdate和updated对比

我们像上面对比beforeMountmounted函数时一样,将root标签里面的innerHTML打印出来看看

beforeUpdate(){
    console.log(document.getElementById('root').innerHTML, 'beforeUpdate函数')
},
updated(){
    console.log(document.getElementById('root').innerHTML, 'updated函数')
},

image.png

根据浏览器中的输出内容可以看出,在beforeUpdate函数执行的时候,还未更新data中的数据,所以打印出来的还是之前的innerHTML内容;但是当更新完成之后,就会在updated函数中打印出新的innerHTML内容了。

把上面的生命周期函数搞懂之后,接下来就是最后两个生命周期函数了。

当vue实例创建完成之后,页面也会挂载到id=root的节点上,但是当我们不想要挂载了,想要把vue实例给销毁掉,那我们应该怎么操作呢?

  • 上面生命周期的图示中已经给到答案了,就是用app.unmount函数可以模拟操作销毁vue实例

6uoyi-c0iuq.gif

当执行app.unmount函数之后,页面上渲染的内容也被清空了,此时也就表示vue实例被销毁了。

  • beforeUnmount:当vue应用失效时,自动执行的函数
  • unmounted:当vue应用失效时,且DOM完全销毁之后,自动执行的函数
beforeUnmount(){
    console.log('beforeUnmount函数')
},
unmounted(){
    console.log('unmounted函数')
},

image.png

beforeUnmount和unmounted对比

同样,我们可以在这两个函数里面打印innerHTML来看看最终的效果

beforeUnmount(){
    console.log(document.getElementById('root').innerHTML, 'beforeUnmount函数')
},
unmounted(){
    console.log(document.getElementById('root').innerHTML, 'unmounted函数')
},

image.png

在页面销毁之前,也就是beforeUnmount函数执行时,页面的内容还是不变的;当页面彻底销毁之后,unmounted函数打印出来的内容就没有vue实例里面的任何节点内容了。

总结

在本节内容中,我们主要学习了vue所有的生命周期函数:beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeUnmountunmounted

但是生命周期这么多,该如何使用呢?在后面的文章中,会用各种案例带着大家对生命周期的使用有更多的了解。