vue使用:生命周期
目录:
vue生命周期图示
vue生命周期图示,下边会介绍各个阶段,可以用来做什么
beforeCreate
beforeCreate阶段,是实例初始化之后,但是还没有进行数据观测(data observer)和event/watcher事件配置之前被调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
{{ name }}
<button @click="myClick">点击修改数据</button>
</div>
<script>
new Vue({
el: "#app",
data: {
name: "wanghongyu"
},
methods: {
init: function () {
console.log(this.name)
},
myClick: function () {
this.name = "WHY";
}
},
beforeCreate() {
console.group("beforeCreate");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
});
</script>
</body>
</html>
浏览器console显示
beforeCreate
el: undefined
data: undefined
name: undefined
init: undefined
myClick: undefined
innerHTML:
{{ name }}
<button @click="myClick">点击修改数据</button>
可以看到只有基础的innerHTML,可以用于创建实例的时候向后端发送请求或者记录一下请求日志等
created
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测,属性和方法的运算,watch/event事件回调。挂载阶段还没开始,$el
属性目前不可见。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
{{ name }}
<button @click="myClick">点击修改数据</button>
</div>
<script>
new Vue({
el: "#app",
data: {
name: "wanghongyu"
},
methods: {
init: function () {
console.log(this.name)
},
myClick: function () {
this.name = "WHY";
}
},
beforeCreate() {
console.group("beforeCreate");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
created() {
console.group("created");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
});
</script>
</body>
</html>
浏览器console显示
created
el: undefined
data: Object
name: wanghongyu
init: function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
myClick: function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
innerHTML:
{{ name }}
<button @click="myClick">点击修改数据</button>
可以看到创建完之后数据和方法都有了
beforeMount
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
{{ name }}
<button @click="myClick">点击修改数据</button>
</div>
<script>
new Vue({
el: "#app",
data: {
name: "wanghongyu"
},
methods: {
init: function () {
console.log(this.name);
},
myClick: function () {
this.name = "WHY";
}
},
beforeCreate() {
console.group("beforeCreate");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
created() {
console.group("created");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
beforeMount() {
console.group("beforeMount");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
});
</script>
</body>
</html>
浏览器console显示
beforeMount
el: <div id="app">"
{{ name }}
"<button @click="myClick">点击修改数据</button></div>
data: {__ob__: po}
name: wanghongyu
init: ƒ n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
myClick: ƒ n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
innerHTML:
{{ name }}
<button @click="myClick">点击修改数据</button>
可以看到el已经有了,但是没有被渲染数据
mount
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
{{ name }}
<button @click="myClick">点击修改数据</button>
</div>
<script>
new Vue({
el: "#app",
data: {
name: "wanghongyu"
},
methods: {
init: function () {
console.log(this.name);
},
myClick: function () {
this.name = "WHY";
}
},
beforeCreate() {
console.group("beforeCreate");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
created() {
console.group("create");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
beforeMount() {
console.group("beforeMount");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
mounted() {
console.group("mounted");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
});
</script>
</body>
</html>
浏览器console显示
mounted
el: <div id="app">"
wanghongyu
"<button>点击修改数据</button></div>
data: {__ob__: po}
name: wanghongyu
init: ƒ n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
myClick: ƒ n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
innerHTML:
wanghongyu
<button>点击修改数据</button>
beforeUpdate
在数据更新前调用,更适合在更新前访问DOM,比如移除添加的事件监听器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
{{ name }}
<button @click="myClick">点击修改数据</button>
</div>
<script>
new Vue({
el: "#app",
data: {
name: "wanghongyu"
},
methods: {
init: function () {
console.log(this.name);
},
myClick: function () {
this.name = "WHY";
}
},
beforeCreate() {
console.group("beforeCreate");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
created() {
console.group("create");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
beforeMount() {
console.group("beforeMount");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
mounted() {
console.group("mounted");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
beforeUpdate() {
console.group("beforeUpdate");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
}
});
</script>
</body>
</html>
需要进行点击,浏览器console显示
beforeUpdate
el: <div id="app">"
WHY
"<button>点击修改数据</button></div>
data: {__ob__: po}
name: WHY
init: ƒ n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
myClick: ƒ n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
innerHTML:
wanghongyu
<button>点击修改数据</button>
可以看到el和data其实已经变化,但是innerHTML还没有被改变
updated
由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子
当这个钩子被调用时,组件DOM已经更新,所以你现在可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或watcher取代。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
{{ name }}
<button @click="myClick">点击修改数据</button>
</div>
<script>
new Vue({
el: "#app",
data: {
name: "wanghongyu"
},
methods: {
init: function () {
console.log(this.name);
},
myClick: function () {
this.name = "WHY";
}
},
beforeCreate() {
console.group("beforeCreate");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
created() {
console.group("create");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
beforeMount() {
console.group("beforeMount");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
mounted() {
console.group("mounted");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
beforeUpdate() {
console.group("beforeUpdate");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
},
updated() {
console.group("updated");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("name: ", this.name);
console.log("init: ", this.init);
console.log("myClick: ", this.myClick);
console.log("innerHTML: ", document.getElementById("app").innerHTML);
}
});
</script>
</body>
</html>
需要进行点击,浏览器console显示
updated
es601.html:74 el: <div id="app">"
WHY
"<button>点击修改数据</button></div>
es601.html:75 data: {__ob__: po}
es601.html:76 name: WHY
es601.html:77 init: ƒ n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
es601.html:78 myClick: ƒ n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}
es601.html:79 innerHTML:
WHY
<button>点击修改数据</button>
beforeDestroy
实例销毁之前调用。在这一步,实例仍然完全可用。频繁的创建和销毁组件对性能的影响很大,因此可以使用activated和deactivated。
在父组件操作isShow,然后控制子组件Laside是否存在
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<App></App>
</div>
<script>
let Laside = {
template: `
<div>
<h1>{{ mes }}</h1>
<button @click="changeData">点击修改数据</button>
</div>
`,
data () {
return {
mes: "Hello Vue!"
}
},
methods: {
changeData: function () {
this.mes = "why is here!";
}
},
// 组件的创建和销毁对性能有影响
beforeDestroy() {
console.group("beforeDestroy");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("mes: ", this.mes);
},
};
let App = {
template: `
<div >
<Laside v-if="isShow"></Laside>
<button @click="showHide">创建消除组件</button>
</div>
`,
components: {
"Laside": Laside,
},
methods: {
showHide: function () {
this.isShow = !this.isShow;
}
},
data () {
return {
isShow: true,
}
}
};
new Vue({
el: "#app",
// 在template中使用组件与在body中使用组件是一样的
// template: `<cont></cont>`,
components: {
App,
}
})
</script>
</body>
</html>
多次点击发现,之后在销毁的之后console里可以看到
beforeDestroy
el: <div><h1>Hello Vue!</h1><button>点击修改数据</button></div>
data: {__ob__: po}
mes: Hello Vue!
destroyed
Vue实例销毁后调用。调用后,Vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<App></App>
</div>
<script>
let Laside = {
template: `
<div>
<h1>{{ mes }}</h1>
<button @click="changeData">点击修改数据</button>
</div>
`,
data () {
return {
mes: "Hello Vue!"
}
},
methods: {
changeData: function () {
this.mes = "why is here!";
}
},
// 组件的创建和销毁对性能有影响
beforeDestroy() {
console.group("beforeDestroy");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("mes: ", this.mes);
},
destroyed() {
console.group("destroyed");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("mes: ", this.mes);
}
};
let App = {
template: `
<div >
<Laside v-if="isShow"></Laside>
<button @click="showHide">创建消除组件</button>
</div>
`,
components: {
"Laside": Laside,
},
methods: {
showHide: function () {
this.isShow = !this.isShow;
}
},
data () {
return {
isShow: true,
}
}
};
new Vue({
el: "#app",
// 在template中使用组件与在body中使用组件是一样的
// template: `<cont></cont>`,
components: {
App,
}
})
</script>
</body>
</html>
activated
keep-alive组件激活时调用。<keep-alive>
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<App></App>
</div>
<script>
let Laside = {
template: `
<div>
<h1>{{ mes }}</h1>
<button @click="changeData">点击修改数据</button>
</div>
`,
data () {
return {
mes: "Hello Vue!"
}
},
methods: {
changeData: function () {
this.mes = "why is here!";
}
},
activated() {
console.group("activated");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("mes: ", this.mes);
},
};
let App = {
template: `
<div >
<keep-alive>
<Laside v-if="isShow"></Laside>
</keep-alive>
<button @click="showHide">创建消除组件</button>
</div>
`,
components: {
"Laside": Laside,
},
methods: {
showHide: function () {
this.isShow = !this.isShow;
}
},
data () {
return {
isShow: true,
}
}
};
new Vue({
el: "#app",
// 在template中使用组件与在body中使用组件是一样的
// template: `<cont></cont>`,
components: {
App,
}
})
</script>
</body>
</html>
浏览器console显示
activated
el: <div><h1>Hello Vue!</h1><button>点击修改数据</button></div>
data: {__ob__: po}
mes: Hello Vue!
deactivated
keep-alive组件停用时调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<App></App>
</div>
<script>
let Laside = {
template: `
<div>
<h1>{{ mes }}</h1>
<button @click="changeData">点击修改数据</button>
</div>
`,
data () {
return {
mes: "Hello Vue!"
}
},
methods: {
changeData: function () {
this.mes = "why is here!";
}
},
activated() {
console.group("activated");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("mes: ", this.mes);
},
deactivated() {
console.group("deactivated");
console.log("el: ", this.$el);
console.log("data: ", this.$data);
console.log("mes: ", this.mes);
}
};
let App = {
template: `
<div >
<keep-alive>
<Laside v-if="isShow"></Laside>
</keep-alive>
<button @click="showHide">创建消除组件</button>
</div>
`,
components: {
"Laside": Laside,
},
methods: {
showHide: function () {
this.isShow = !this.isShow;
}
},
data () {
return {
isShow: true,
}
}
};
new Vue({
el: "#app",
// 在template中使用组件与在body中使用组件是一样的
// template: `<cont></cont>`,
components: {
App,
}
})
</script>
</body>
</html>
频繁点击浏览器console显示
activated
el: <div><h1>Hello Vue!</h1><button>点击修改数据</button></div>
data: {__ob__: po}
mes: Hello Vue!
deactivated
el: <div><h1>Hello Vue!</h1><button>点击修改数据</button></div>
data: {__ob__: po}
mes: Hello Vue!
activated
el: <div><h1>Hello Vue!</h1><button>点击修改数据</button></div>
data: {__ob__: po}
mes: Hello Vue!
总结
- beforeCreate 实例创建之前除标签外,所有vue需要的数据,事件都不存在
- created 创建实例,data被解析到,el还没有找到
- beforeMount 标签找到,数据还没有被渲染,事件也没有被监听
- Mounted 数据被渲染,开始监听事件
- beforeUpdate 数据被更新在虚拟DOM,但是没有渲染到页面上
- updated 使用diff算法将虚拟DOM上的数据应用到页面上,此时真实DOM的数据被修改
- beforeDestroy 所有数据都存在
- destory 所有数据都有(在虚拟DOM中)
- keep-alive提供缓存被消除的标签,用active和deactive取代了beforeDestroy和destory