2020-3-24-vue生命周期

vue生命周期的理解

一、各函数详解

一张熟悉的图片
8OA69x.md.png

各函数详解

生命周期钩子组件状态应用
beforeCreate实例初始化时执行,this指向创建的实例;dom节点未加载;不能访问到data、computed、watch、methods上的方法和数据初始化非响应式变量
created实例初始化时执行;dom节点未加载;可访问data、computed、watch、methods上的方法和数据,但更改数据不造成影响;不能访问到 e l 属 性 , el属性, elref属性内容为空数组ajax请求,初始化事件的绑定
beforeMount渲染之前调用,beforeMount之前,会找到对应的template,编译成虚拟dom,即将放入render函数
mounted组件初始化最后一步;虚拟dom在render函数里替换对应的el挂载点,渲染成真实dom节点,此时可以通过DOM API获取到DOM节点,$ref属性可以访问常用于获取VNode信息和操作,ajax请求
beforeupdate数据更新时调用,可获取更新前的数据适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器
updated新虚拟DOM与就虚拟dom对比,通过diff算法比出差异,再重新渲染避免在这个钩子函数中操作数据,可能陷入死循环
beforeDestroyvm.$destroy()触发时调用,实例仍然完全可用,this仍能获取到实例常用于销毁定时器、解绑全局事件、销毁插件对象等操作
destroyedVue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁;dom节点仍存在,但失去双向绑定功能

二、单组件生命周期

如下,body里有一个组件:

    <div id="app">
        <my-component></my-component>
    </div>

    <template id="my-component">
        <div>
            <h1 id="title">父组件文本内容</h1>
            <p><input type="text" v-model="msg"></p>
            <button @click="destroy">destroy</button>
        </div>
    </template>

    <script>
        Vue.component("my-component", {
            template: "#my-component",
            data() {
                return {
                    msg: "data"
                }
            },
            beforeCreate() {
                console.log("beforeCreate....", this.msg2, document.getElementById("title"))
            },
            created() {
                console.log("created...", this.msg2, document.getElementById("title"))
            },
            beforeMount() {
                console.log("beforeMount....", this.msg2, document.getElementById("title"))
            },
            mounted() {
                console.log("mounted.....", this.msg2, document.getElementById("title"))
            },
            beforeUpdate() {
                console.log("beforeUpdate....", this.msg2, document.getElementById("title"))
            },
            updated() {
                console.log("updated....", this.msg2, document.getElementById("title"))
            },
            beforeDestroy() {
                console.log("beforeDestroy....", this.msg2, document.getElementById("title"))
            },
            destroyed() {
                console.log("destroyed....", this.msg2, document.getElementById("title"))
            },
            methods: {
                destroy() {
                    this.$destroy()
                }
            }
        })

        new Vue({}).$mount("#app");
    </script>

第一次打开时,为初始化过程,调用了四个钩子函数,打印如下:

beforeCreate.... undefined null
created... undefined null
beforeMount.... undefined null
mounted..... undefined <h1 id=​"title">​父组件文本内容​</h1>​

数据改变时,调用了两个钩子函数,打印如下:

beforeUpdate.... undefined <h1 id=​"title">​父组件文本内容​</h1>​
updated.... undefined <h1 id=​"title">​父组件文本内容​</h1>​

销毁时,调用两个钩子函数,打印如下:

beforeDestroy.... undefined <h1 id=​"title">​父组件文本内容​</h1>​
destroyed.... undefined <h1 id=​"title">​父组件文本内容​</h1>​

三、父子组件生命周期

如下,body里有一对父子组件:

    <div id="app">
        <my-component></my-component>
    </div>

    <template id="my-component">
        <div>
            <h1 id="title">父组件文本内容</h1>
            <p><input type="text" v-model="msg"></p>
            <button @click="destroy">destroy</button>
            <son-component></son-component>
        </div>
    </template>

    <template id="son-component">
        <div>
            <h1 id="title2">子组件文本内容</h1>
            <p><input type="text" v-model="msg2"></p>
            <button @click="destroy2">destroy</button>
        </div>
    </template>

    <script>
        Vue.component("my-component", {
            template: "#my-component",
            data() {
                return {
                    msg: "data"
                }
            },
            beforeCreate() {
                console.log("parent beforeCreate....", this.msg, document.getElementById("title"))
            },
            created() {
                console.log("parent created...", this.msg, document.getElementById("title"))
            },
            beforeMount() {
                console.log("parent beforeMount....", this.msg, document.getElementById("title"))
            },
            mounted() {
                console.log("parent mounted.....", this.msg, document.getElementById("title"))
            },
            beforeUpdate() {
                console.log("parent beforeUpdate....", this.msg, document.getElementById("title"))
            },
            updated() {
                console.log("parent updated....", this.msg, document.getElementById("title"))
            },
            beforeDestroy() {
                console.log("parent beforeDestroy....", this.msg, document.getElementById("title"))
            },
            destroyed() {
                console.log("parent destroyed....", this.msg, document.getElementById("title"))
            },
            methods: {
                destroy() {
                    this.$destroy()
                }
            }
        })

        Vue.component("son-component", {
            template: "#son-component",
            data() {
                return {
                    msg2: "son-data"
                }
            },
            beforeCreate() {
                console.log("son beforeCreate....", this.msg2, document.getElementById("title2"))
            },
            created() {
                console.log("son created...", this.msg2, document.getElementById("title2"))
            },
            beforeMount() {
                console.log("son beforeMount....", this.msg2, document.getElementById("title2"))
            },
            mounted() {
                console.log("son mounted.....", this.msg2, document.getElementById("title2"))
            },
            beforeUpdate() {
                console.log("son beforeUpdate....", this.msg2, document.getElementById("title2"))
            },
            updated() {
                console.log("son updated....", this.msg2, document.getElementById("title2"))
            },
            beforeDestroy() {
                console.log("son beforeDestroy....", this.msg2, document.getElementById("title2"))
            },
            destroyed() {
                console.log("son destroyed....", this.msg2, document.getElementById("title2"))
            },
            methods: {
                destroy2() {
                    this.$destroy()
                }
            }
        })
        new Vue({}).$mount("#app");
    </script>

第一次打开时,为初始化过程,可见父组件渲染完再到子组件,打印如下:

parent beforeCreate.... undefined null
parent created... data null
parent beforeMount.... data null
son beforeCreate.... undefined null
son created... son-data null
son beforeMount.... son-data null
son mounted..... son-data <h1 id=​"title2">​子组件文本内容​</h1>​
parent mounted..... data <h1 id=​"title">​父组件文本内容​</h1>​

数据改变时,分别调用本身的beforeUpdate和update,与单组件一致;

子组件销毁时,子组件两个销毁函数被调用,打印如下:

son beforeDestroy.... son-data <h1 id=​"title2">​子组件文本内容​</h1>​
son destroyed.... son-data <h1 id=​"title2">​子组件文本内容​</h1>​

父组件销毁时,父子销毁函数都会被调用,并且可见子组件先销毁,打印如下:

parent beforeDestroy.... data <h1 id=​"title">​父组件文本内容​</h1>​
son beforeDestroy.... son-data <h1 id=​"title2">​子组件文本内容​</h1>​
son destroyed.... son-data <h1 id=​"title2">​子组件文本内容​</h1>​
parent destroyed.... data <h1 id=​"title">​父组件文本内容​</h1>​

四、兄弟组件生命周期

如下,body里有一对兄弟组件

    <div id="app">
        <my-component></my-component>
        <bro-component></bro-component>
    </div>

    <template id="my-component">
        <div>
            <h1 id="title">哥哥组件文本内容</h1>
            <p><input type="text" v-model="msg"></p>
            <button @click="destroy">destroy</button>
        </div>
    </template>

    <template id="bro-component">
        <div>
            <h1 id="title2">弟弟组件文本内容</h1>
            <p><input type="text" v-model="msg2"></p>
            <button @click="destroy2">destroy</button>
        </div>
    </template>

    <script>
        Vue.component("my-component", {
            template: "#my-component",
            data() {
                return {
                    msg: "data"
                }
            },
            beforeCreate() {
                console.log("bro1 beforeCreate....", this.msg, document.getElementById("title"))
            },
            created() {
                console.log("bro1 created...", this.msg, document.getElementById("title"))
            },
            beforeMount() {
                console.log("bro1 beforeMount....", this.msg, document.getElementById("title"))
            },
            mounted() {
                console.log("bro1 mounted.....", this.msg, document.getElementById("title"))
            },
            beforeUpdate() {
                console.log("bro1 beforeUpdate....", this.msg, document.getElementById("title"))
            },
            updated() {
                console.log("bro1 updated....", this.msg, document.getElementById("title"))
            },
            beforeDestroy() {
                console.log("bro1 beforeDestroy....", this.msg, document.getElementById("title"))
            },
            destroyed() {
                console.log("bro1 destroyed....", this.msg, document.getElementById("title"))
            },
            methods: {
                destroy() {
                    this.$destroy()
                }
            }
        })

        Vue.component("bro-component", {
            template: "#bro-component",
            data() {
                return {
                    msg2: "bro2-data"
                }
            },
            beforeCreate() {
                console.log("bro2 beforeCreate....", this.msg2, document.getElementById("title2"))
            },
            created() {
                console.log("bro2 created...", this.msg2, document.getElementById("title2"))
            },
            beforeMount() {
                console.log("bro2 beforeMount....", this.msg2, document.getElementById("title2"))
            },
            mounted() {
                console.log("bro2 mounted.....", this.msg2, document.getElementById("title2"))
            },
            beforeUpdate() {
                console.log("bro2 beforeUpdate....", this.msg2, document.getElementById("title2"))
            },
            updated() {
                console.log("bro2 updated....", this.msg2, document.getElementById("title2"))
            },
            beforeDestroy() {
                console.log("bro2 beforeDestroy....", this.msg2, document.getElementById("title2"))
            },
            destroyed() {
                console.log("bro2 destroyed....", this.msg2, document.getElementById("title2"))
            },
            methods: {
                destroy2() {
                    this.$destroy()
                }
            }
        })
        new Vue({}).$mount("#app");
    </script>

第一次打开时,为初始化过程;按顺序,先初始化,再渲染;打印如下:

bro1 beforeCreate.... undefined null
bro1 created... data null
bro1 beforeMount.... data null
bro2 beforeCreate.... undefined null
bro2 created... bro2-data null
bro2 beforeMount.... bro2-data null
bro1 mounted..... data <h1 id=​"title">​哥哥组件文本内容​</h1>​
bro2 mounted..... bro2-data <h1 id=​"title2">​弟弟组件文本内容​</h1>​

数据改变时,分别调用本身的beforeUpdate和updated,与单组件一致;

数据改变时,分别调用本身的beforeDestroy和destroyed,与单组件一致;

五、总结

注意点:

  • vue2.0之后主动调用$destroy()不会移除dom节点,作者不推荐直接destroy这种做法,如果实在需要这样用可以在这个生命周期钩子中手动移除dom节点
  • created阶段的ajax请求与mounted请求的区别:前者页面视图未出现,如果请求信息过多,页面会长时间处于白屏状态

单组件:

  • 初始化组件时,仅执行了beforeCreate/Created/beforeMount/mounted四个钩子函数
  • 当改变data中定义的变量(响应式变量)时,会执行beforeUpdate/updated钩子函数
  • 当切换组件(当前组件未缓存)时,会执行beforeDestory/destroyed钩子函数
  • 初始化和销毁时的生命钩子函数均只会执行一次,beforeUpdate/updated可多次执行

父子组件:

  • 仅当子组件完成挂载后,父组件才会挂载
  • 当子组件完成挂载后,父组件会主动执行一次beforeUpdate/updated钩子函数(仅首次)
  • 父子组件在data变化中是分别监控的,但是在更新props中的数据是关联的(可实践)
  • 销毁父组件时,先将子组件销毁后才会销毁父组件

兄弟组件:

  • 组件的初始化(mounted之前)分开进行,挂载是从上到下依次进行
  • 当没有数据关联时,兄弟组件之间的更新和销毁是互不关联的

参考文章:
[1]https://juejin.im/entry/5aee8fbb518825671952308c
[2]https://cn.vuejs.org/v2/guide/instance.html#%E5%AE%9E%E4%BE%8B%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90
[3]https://segmentfault.com/a/1190000011381906
[4]https://segmentfault.com/a/1190000008010666

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值