欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vue.js入门笔记(十二)--Vue生命周期

程序员文章站 2022-07-01 19:20:10
...

生命周期

每个 Vue 实例在被创建之前都要经过一系列的初始化过程。
Vue.js入门笔记(十二)--Vue生命周期
Vue 在生命周期中有这些状态,beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed。

先是 new Vue(),然后接下来 beforeCreate, beforeCreate 就是在创建之前的意思,在创建之前其实就是啥事都没有,然后接下来它就开始观察数据,然后开始初始化事件,然后接下来就是 created,这时就在创建 Vue 对象。创建完了之后,观察有没有 Vue 接管的区域,有就继续执行,观察有没有模板选项,到了这里开始准备渲染的方法,渲染就是要把浏览器中要显示的内容给准备好。然后走到 beforeMount,在挂载之前什么都没有准备,只是准备要挂载,挂载就是把我们编写的代码加载到浏览器中去显示,挂载之前就是显示之前,之后继续创建 Vue 的一些细节,并且准备 el 接管区域的数据,然后开始挂载,也就是把数据加载到页面中显示。

那加载完了之后,数据显示出来就应该结束了,为什么还有 beforeUpdate,updated,beforeDestroy,destroyed 呢?如果我们对数据有更新,在更新之前,到达一个声明周期的执行点,然后更新数据,更新完数据后 Vue 希望你能看到更新之后的数据,所以它在那还有一个更新操作,更新操作的同时也会对页面进行重新加载。更新的这个生命周期的执行点,有更新它才有,没有更新它就没有。

然后走到 beforeDestroy,也就是在销毁之前,这个时候你调用了销毁,需要它销毁的时候它才会有 beforeDestroy 和 destroyed 这两个生命周期的执行点。如果你没有调用销毁,它也不会触发销毁的这两个生命周期的执行点。

Vue 在实例化的过程中,会调用这些生命周期的钩子,给我们提供了执行自定义逻辑的机会。那么,在这些 Vue 钩子中,Vue 实例到底执行了那些操作,可以参考下面的 Demo。

Demo

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>vuejs生命周期</title>
		<script src="js/vue.js"></script>
	</head>

	<body>
		<div id="app">
			{{message}}
		</div>
	</body>
	<script>
		var vm = new Vue({
			el: "#app",
			data: {
				message: 'hello world'
			},
			beforeCreate: function() {
				console.log(this);
				showData('创建vue实例前', this);
			},
			created: function() {
				showData('创建vue实例后', this);
			},
			beforeMount: function() {
				showData('挂载到dom前', this);
			},
			mounted: function() {
				showData('挂载到dom后', this);
			},
			beforeUpdate: function() {
				showData('数据变化更新前', this);
			},
			updated: function() {
				showData('数据变化更新后', this);
			},
			beforeDestroy: function() {
				vm.test = "3333";
				showData('vue实例销毁前', this);
			},
			destroyed: function() {
				showData('vue实例销毁后', this);
			}
		});

		function realDom() {
			console.log('真实dom结构:' + document.getElementById('app').innerHTML);
		}

		function showData(process, obj) {
			console.log(process);
			console.log('data 数据:' + obj.message)
			console.log('挂载的对象:')
			console.log(obj.$el)
			realDom();
			console.log('------------------')
			console.log('------------------')
		}
		vm.message = "good...";
		vm.$destroy(); 
	</script>
</html>

首先执行下面的代码,观察四个最基本的生命周期执行。

var vm = new Vue({
    el: "#app",
    data: {
        message: 'hello world'
    },
    beforeCreate: function() {
        console.log(this);
        showData('创建vue实例前', this);
    },
    created: function() {
        showData('创建vue实例后', this);
    },
    beforeMount: function() {
        showData('挂载到dom前', this);
    },
    mounted: function() {
        showData('挂载到dom后', this);
    },
    beforeUpdate: function() {
        showData('数据变化更新前', this);
    },
    updated: function() {
        showData('数据变化更新后', this);
    },
    beforeDestroy: function() {
        vm.test = "3333";
        showData('vue实例销毁前', this);
    },
    destroyed: function() {
        showData('vue实例销毁后', this);
    }
});

function realDom() {
    console.log('真实dom结构:' + document.getElementById('app').innerHTML);
}

function showData(process, obj) {
    console.log(process);
    console.log('data 数据:' + obj.message)
    console.log('挂载的对象:')
    console.log(obj.$el)
    realDom();
    console.log('------------------')
    console.log('------------------')
}
//vm.message = "good...";
//vm.$destroy(); 

控制台输出结果:
Vue.js入门笔记(十二)--Vue生命周期
然后执行下面的代码,观察与更新相关的生命周期执行点。

var vm = new Vue({
    el: "#app",
    data: {
        message: 'hello world'
    },
    beforeCreate: function() {
        console.log(this);
        showData('创建vue实例前', this);
    },
    created: function() {
        showData('创建vue实例后', this);
    },
    beforeMount: function() {
        showData('挂载到dom前', this);
    },
    mounted: function() {
        showData('挂载到dom后', this);
    },
    beforeUpdate: function() {
        showData('数据变化更新前', this);
    },
    updated: function() {
        showData('数据变化更新后', this);
    },
    beforeDestroy: function() {
        vm.test = "3333";
        showData('vue实例销毁前', this);
    },
    destroyed: function() {
        showData('vue实例销毁后', this);
    }
});

function realDom() {
    console.log('真实dom结构:' + document.getElementById('app').innerHTML);
}

function showData(process, obj) {
    console.log(process);
    console.log('data 数据:' + obj.message)
    console.log('挂载的对象:')
    console.log(obj.$el)
    realDom();
    console.log('------------------')
    console.log('------------------')
}
vm.message = "good...";
//vm.$destroy();

控制台输出结果:
Vue.js入门笔记(十二)--Vue生命周期
最后执行下面的代码,观察与销毁相关的生命周期执行点。

var vm = new Vue({
    el: "#app",
    data: {
        message: 'hello world'
    },
    beforeCreate: function() {
        console.log(this);
        showData('创建vue实例前', this);
    },
    created: function() {
        showData('创建vue实例后', this);
    },
    beforeMount: function() {
        showData('挂载到dom前', this);
    },
    mounted: function() {
        showData('挂载到dom后', this);
    },
    beforeUpdate: function() {
        showData('数据变化更新前', this);
    },
    updated: function() {
        showData('数据变化更新后', this);
    },
    beforeDestroy: function() {
        vm.test = "3333";
        showData('vue实例销毁前', this);
    },
    destroyed: function() {
        showData('vue实例销毁后', this);
    }
});

function realDom() {
    console.log('真实dom结构:' + document.getElementById('app').innerHTML);
}

function showData(process, obj) {
    console.log(process);
    console.log('data 数据:' + obj.message)
    console.log('挂载的对象:')
    console.log(obj.$el)
    realDom();
    console.log('------------------')
    console.log('------------------')
}
//vm.message = "good...";
vm.$destroy();

控制台输出结果:
Vue.js入门笔记(十二)--Vue生命周期
可以观察到,实例销毁后,data 数据、挂载的对象、真实 dom 结构都没有任何变化,因为销毁的只是 Vue 对象,不会把页面中的数据搞没。

具体应用

如何利用这些生命周期的执行点?比如说,我希望在页面加载的时候执行一些操作、显示一些数据,我就可以选择生命周期里的一些方法来执行。比如说,我想在页面加载的时候查询一下列表,这个时候需要在对象创建完之后,把数据准备出来。从上面的 Demo 中可以看到,创建 Vue 实例后,data 数据就有具体值了,所以我可以用 created 方法去触发一个请求,把数据查询出来,然后在后面的操作中把数据遍历,在列表中显示。

每个方法都有它应用的时间点,当你有实际需求,需要在某个时间点做某件事时,那个时间点正好和生命周期中的某个方法契合,就可以选用这个方法去操作。

总结

Vue 对象初始化过程中,会执行到 beforeCreate,created,beforeMount,mounted 这几个钩子的内容:

  • beforeCreate:数据还没有监听,没有绑定到 Vue 对象实例,同时也没有挂载对象
  • created:数据已经绑定到了对象实例,但是还没有挂载对象
  • beforeMount:模板已经编译好了,根据数据和模板已经生成了对应的元素对象,将数据对象关联到了对象的 el 属性,el 属性是一个 HTMLElement 对象,也就是这个阶段,Vue 实例通过原生的 createElement 等方法来创建这个 HTML 片段,准备注入到我们 Vue 实例指明的 el 属性所对应的挂载点
  • mounted:将 el 的内容挂载到了 el,相当于我们在 jQuery 执行了 (el).html(el),生成页面上真正的 DOM,其实 DOM 的元素和 el 元素是一致的。在此之后,我们能够用方法来获取到 el 元素下的 DOM 对象,并进行各种操作
  • 当 data 发生改变时,会调用 beforeUpdate 和 updated 方法
    • beforeUpdate:数据更新到 DOM 之前,可以看到 $el 对象已经修改,但是页面上 DOM 的数据还没有发生改变
    • updated:DOM 结构会通过虚拟 DOM 的原则,找到需要更新页面的 DOM 结构的最小路径,将改变更新到 DOM 上面,完成更新
  • beforeDestroy,destroed:实例的销毁,Vue 实例还是存在的,只是解绑了事件的监听还有 watcher 对象数据与 view 的绑定,即数据驱动