记vuejs生命周期一次体验
in Vuejs with 0 comment

记vuejs生命周期一次体验

in Vuejs with 0 comment

提示:下面体验的 vue version 是 ^2.5.13

一.Vue生命周期简介

官网:https://cn.vuejs.org/v2/api/#beforeCreate
Vue实例从创建到销毁的过程,就是生命周期。详细来说也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程。
首先我们来看一下官网的生命周期图(我自己做了一点点注释):

alt text

Vue提供给我们的钩子为上图的红色的文字

二.钩子详解

注释:下面代码使用组件方式

1.beforeCreate

在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。

<style>

</style>

<template> 
<div>
</div>
</template>

<script>
export default {
    name: 'Test',
    data(){
        return{
             message:'this is mseeage'
        }
    },
    watch:{
        message:function(){
            console.log('watch:','message 变了')   
        }
    },
    methods: {
        init:function(){
            console.log('这是初始化方法')
        }
    },
    //我们在beforeCreate钩子中调用Vue的data和method
    beforeCreate:function(){
        console.log("beforeCreate",this.message);
        this.init();
    }
}
</script>

我们在上面的例子中在的beforeCreate钩子中调用Vue的data和method,来看一下结果:

alt text

可以看到Vue中的data和方法都是去不到的,并且是在wath之前执行

2.created

实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。 主要应用:调用数据,调用方法,调用异步函数

<style>

</style>

<template> 
<div>

    <ul>
        <li v-for="(item,index) in list" :key="index">{{ item }} -- {{message}}</li>
    </ul>

   <p ref="pnode">p1</p>
    <p id="myAnchor">p1</p>
    <p>p1</p>

</div>
</template>

<script>
export default {
    name: 'Test',
    data () {
        return {
           message:'this is 张炳 message!嘿嘿!',
            list:['aaaaaaaa','bbbbbbb','ccccccc']
        }
    },
    //时刻监测数据message的变化,一但那变化就会吊该函数
    watch:{
        //message必须和监测的data名字一样
        message:function(){
            console.log('watch:','message 变了')
        }
    },
    methods: {
           foo:function(){
                console.log('foo : ','这是初始化方法')
            }
    },
    //created钩子
    created:function(){
        //调用Vue的data
        console.log("created : ",this.message);
        //调用Vue方法
        this.foo();

        console.log(this.$refs);  //是空,更别说 获取到 this.$refs.pnode了

        //无法获取到个数
        console.log('li数量:',document.getElementsByTagName('li').length);

        console.log('p个数:',document.getElementsByTagName('p').length);

        //均无法获取到dom,无法设置
        document.getElementsByTagName('p')[0].innerHTML = 'hello! zhangbing'
        document.getElementById('myAnchor').innerHTML="bye!  zhangbing";
    },

}
</script>

alt text

可以看到:created钩子可以获取Vue的data,可以调用Vue方法 , 但 挂载阶段还没开始,$el 属性目前不可见。 this.$refs为空对象,获取dom的个数,和设置dom的innerHTML均失效,出现报错。

3.beforeMount

<style>

</style>

<template> 
<div>
    <ul>
        <li v-for="(item,index) in list" :key="index">{{ item }} -- {{message}}</li>
    </ul>

    <p ref="pnode">p1</p>
    <p id="myAnchor">p1</p>
    <p>p1</p>

</div>
</template>

<script>
export default {
    name: 'Test',
    data () {
        return {
           message:'this is 张炳 message!嘿嘿!',
            list:['aaaaaaaa','bbbbbbb','ccccccc']
        }
    },
    beforeMount: function () {
        console.log('beforeMount: li数量:',document.getElementsByTagName('li').length);
        console.log('beforeMount: p数量:',document.getElementsByTagName('p').length);
    }
}
</script>

alt text

官方文档:在挂载开始之前被调用:相关的 render 函数首次被调用。 beforeMount挂载钩子,此时还没有生成HTML到页面中,没法获取 dom的数量。

4.mounted

<style>
</style>
<template> 
<div>
    <ul>
        <li v-for="(item,index) in list" :key="index">{{ item }} -- {{message}}</li>
    </ul>
    <p ref="pnode">p1</p>
    <p id="myAnchor">p1</p>
    <p>p1</p>
</div>
</template>
<script>
export default {
    name: 'Test',
    data () {
        return {
           message:'this is 张炳 message!嘿嘿!',
            list:['aaaaaaaa','bbbbbbb','ccccccc']
        }
    },
    mounted: function () {
        console.log('mounted: li数量:',document.getElementsByTagName('li').length);
        console.log('mounted: p数量:',document.getElementsByTagName('p').length);
    }
}
</script>

alt text

el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。看到可以正常获取到dom的个数了

5.beforeUpdate

<style>
</style>
<template> 
<div>
    <ul>
        <li v-for="(item,index) in list" :key="index">{{ item }} -- {{message}}</li>
    </ul>
    <p ref="pnode"> p1</p>
    <p id="myAnchor">p1</p>
    <p>p1</p>

    <input type="button" @click="changeMessage" value="更改数据">
</div>
</template>
<script>
export default {
    name: 'Test',
    data () {
        return {
           message:'this is 张炳 message!嘿嘿!',
            list:['aaaaaaaa','bbbbbbb','ccccccc']
        }
    },
    beforeUpdate: function () {
        console.log('beforeUpdate 钩子执行...');
        console.log('beforeUpdate:'+this.message);
    },
    methods:{
        changeMessage(){
            this.message = 'hello. 张炳,我更改数据了'+ Math.random();
        }
    }
}
</script>

alt text

点击按钮 3次,出现上面的图;

数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。要明确这句话:意思是数据更新后了调用这个钩子,但是在渲染虚拟dom之前!!!所以你看到的 chrome 调控台的数据也是 数据更新后的数据!

同时,你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。 当我们更改Vue的任何数据,都会触发该函数。

6.updated

<style>
</style>
<template> 
<div>
    <ul>
        <li v-for="(item,index) in list" :key="index">{{ item }} -- {{message}}</li>
    </ul>
    <p ref="pnode"> p1</p>
    <p id="myAnchor">p1</p>
    <p>p1</p>

    <input type="button" @click="changeMessage" value="更改数据">
</div>
</template>
<script>
export default {
    name: 'Test',
    data () {
        return {
           message:'this is 张炳 message!嘿嘿!',
            list:['aaaaaaaa','bbbbbbb','ccccccc']
        }
    },
    updated: function () {
        console.log('updated 钩子执行...');
        console.log('updated:'+this.message);
    },
    methods:{
        changeMessage(){
            this.message = 'hello. 张炳,我更改数据了'+ Math.random();
        }
    }
}
</script>

alt text

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环 。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。

7.beforeDestroy

实例销毁之前调用。在这一步,实例仍然完全可用。

8.destroyed

Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

<div id="app">
</div>
<script type="text/javascript">
    //实例化Vue
    var app = new Vue({
        el:'#app',
        data:{
            message:'this is mseeage',
        },
        beforeDestroy: function () {
            console.log('beforeDestroy 钩子执行...',this.message)
        },
        destroyed: function () {
            console.log('destroyed 钩子执行...',this.message)
        }
    })
    //销毁Vue实例,触发beforeDestroy和destroyed函数
    app.$destroy()
</script>   

alt text

Responses