从今天开始我们开始学习 Vue 生命周期钩子,就像人的一生一样短暂,充满着未知情况,从一开始的出生,小孩,少年,青年,中年,晚年,直到死亡那刻来临,每一个阶段都会处理不同的事情,人的整个生涯就算走完。Vue 实例也一样有着一个完整的生命周期,也就是说从开始创建,初始化数据,编译模板,挂载DOM,渲染-更新-渲染,卸载等一系列过程,构成为 Vue 实例的生命周期,钩子就是在某个阶段做一些处理。
在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还没创建,其中 data, el 并没有被初始化,因此没有办法获取 methods, data, computed, watch 等上的方法,属性。
我们先在 src/main.js 写下代码:
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
// let app = createApp(App)
let app = createApp({
template: `
<div>在data中监测的数据a -- {{a}}</div>
<div>不在data中监测的数据b --- {{b}}</div>
<props-demo-simple size="16" my-message="hahaja"></props-demo-simple>
<props-demo-advanced :height="100" :age="100"></props-demo-advanced>
`,
data() {
return {
a: 1,
b: {
name: 'haha'
}
}
},
methods: {
plus() {
console.log(this.a + 1)
},
someMethod() {
console.log("b发生变化了")
}
},
beforeCreate() {
console.log("beforeCreate", "this.data===", this.data, "$el=====" , this.$el)
}
})
app.use(store).use(router).mount('#app')
运行之后,我们看到控制台打印的数据如下:
beforeCreate this.data=== undefined $el===== null
此时实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测,计算属性,watch/event 事件监听,完成 data 数据的初始化, el 此时还没挂载,所以不可见,这是一个常见的生命周期,因为你可以调用 methods 中方法,改变 data 中的数据,并且修改可以通过 Vue 响应式绑定在页面上,获取计算属性等,在这个期间我们可以做一些数据请求等。
我们继续向上面的代码添加 created:
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
// let app = createApp(App)
let app = createApp({
template: `
<div>在data中监测的数据a -- {{a}}</div>
<div>不在data中监测的数据b --- {{b}}</div>
<props-demo-simple size="16" my-message="hahaja"></props-demo-simple>
<props-demo-advanced :height="100" :age="100"></props-demo-advanced>
`,
data() {
return {
a: 1,
b: {
name: 'haha'
}
}
},
methods: {
plus() {
console.log(this.a + 1)
},
someMethod() {
console.log("b发生变化了")
}
},
beforeCreate() {
console.log("beforeCreate", "this.$data===", this.$data, "$el=====" , this.$el)
},
created() {
console.log("created", "this.$data===", this.$data, "$el=====" , this.$el)
}
})
app.use(store).use(router).mount('#app')
我们看到控制台打印的数据如下:
beforeCreate this.$data=== {} $el===== null
created this.$data=== Proxy {a: 1, b: {…}}[[Handler]]: Object[[Target]]: Objecta: 1b: name: "haha"__proto__: Object__proto__: Object[[IsRevoked]]: false $el===== null
挂载元素之前被调用,相关的 render 函数首次被调用(虚拟DOM),实例已经完成模板编译,把 data 里面的数据和模板,指令等生成 html, 完成 el 和 data 初始化,注意此时还没将 html 渲染到页面上。
我们继续向上面的代码:
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
// let app = createApp(App)
let app = createApp({
template: `
<div>在data中监测的数据a -- {{a}}</div>
<div>不在data中监测的数据b --- {{b}}</div>
<props-demo-simple size="16" my-message="hahaja"></props-demo-simple>
<props-demo-advanced :height="100" :age="100"></props-demo-advanced>
`,
data() {
return {
a: 1,
b: {
name: 'haha'
}
}
},
methods: {
plus() {
console.log(this.a + 1)
},
someMethod() {
console.log("b发生变化了")
}
},
beforeCreate() {
console.log("beforeCreate", "this.$data===", this.$data, "$el=====" , this.$el)
},
created() {
console.log("created", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeMount() {
console.log("beforeMount", "this.$data===", this.$data, "$el=====" , this.$el)
}
})
app.use(store).use(router).mount('#app')
此时控制台打印的数据如下:
beforeMount this.$data=== Proxy {a: 1, b: {…}} $el===== null
挂载完成之后调用,也就是模板中的 HTML 已经渲染到页面上来了,此时一般可以做一些操作DOM,ajax 请求,mounted 只会执行一次。
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
// let app = createApp(App)
let app = createApp({
template: `
<div>在data中监测的数据a -- {{a}}</div>
<div>不在data中监测的数据b --- {{b}}</div>
<props-demo-simple size="16" my-message="hahaja"></props-demo-simple>
<props-demo-advanced :height="100" :age="100"></props-demo-advanced>
`,
data() {
return {
a: 1,
b: {
name: 'haha'
}
}
},
methods: {
plus() {
console.log(this.a + 1)
},
someMethod() {
console.log("b发生变化了")
}
},
beforeCreate() {
console.log("beforeCreate", "this.$data===", this.$data, "$el=====" , this.$el)
},
created() {
console.log("created", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeMount() {
console.log("beforeMount", "this.$data===", this.$data, "$el=====" , this.$el)
},
mounted() {
console.log("mounted", "this.$data===", this.$data, "$el=====" , this.$el)
}
})
app.use(store).use(router).mount('#app')
我们在控制台打印的数据如下:
mounted this.$data=== Proxy {a: 1, b: {…}} $el===== #text
在数据更新之前被调用,发生在虚拟的 DOM 重新渲染和打补丁之前,可以在该钩子进行更改状态,不会触发附加的重复渲染过程。
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
// let app = createApp(App)
let app = createApp({
template: `
<div>在data中监测的数据a -- {{a}}</div>
<div>不在data中监测的数据b --- {{b}}</div>
<props-demo-simple size="16" my-message="hahaja"></props-demo-simple>
<props-demo-advanced :height="100" :age="100"></props-demo-advanced>
`,
data() {
return {
a: 1,
b: {
name: 'haha'
}
}
},
methods: {
plus() {
console.log(this.a + 1)
},
someMethod() {
console.log("b发生变化了")
}
},
beforeCreate() {
console.log("beforeCreate", "this.$data===", this.$data, "$el=====" , this.$el)
},
created() {
console.log("created", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeMount() {
console.log("beforeMount", "this.$data===", this.$data, "$el=====" , this.$el)
},
mounted() {
console.log("mounted", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeUpdate() {
this.b = {}
console.log("beforeUpdate", "this.$data===", this.$data, "$el=====" , this.$el)
},
})
app.use(store).use(router).mount('#app')
在由于数据更改导致地虚拟DOM重新渲染和打补丁只会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用。
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
// let app = createApp(App)
let app = createApp({
template: `
<div>在data中监测的数据a -- {{a}}</div>
<div>不在data中监测的数据b --- {{b}}</div>
<props-demo-simple size="16" my-message="hahaja"></props-demo-simple>
<props-demo-advanced :height="100" :age="100"></props-demo-advanced>
`,
data() {
return {
a: 1,
b: {
name: 'haha'
}
}
},
methods: {
plus() {
console.log(this.a + 1)
},
someMethod() {
console.log("b发生变化了")
}
},
beforeCreate() {
console.log("beforeCreate", "this.$data===", this.$data, "$el=====" , this.$el)
},
created() {
console.log("created", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeMount() {
console.log("beforeMount", "this.$data===", this.$data, "$el=====" , this.$el)
},
mounted() {
console.log("mounted", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeUpdate() {
this.b = {}
console.log("beforeUpdate", "this.$data===", this.$data, "$el=====" , this.$el)
},
updated() {
console.log("update", "this.$data===", this.$data, "$el=====" , this.$el)
},
})
app.use(store).use(router).mount('#app')
在实例销毁之前调用,实例仍然完全可用,
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
// let app = createApp(App)
let app = createApp({
template: `
<div>在data中监测的数据a -- {{a}}</div>
<div>不在data中监测的数据b --- {{b}}</div>
<props-demo-simple size="16" my-message="hahaja"></props-demo-simple>
<props-demo-advanced :height="100" :age="100"></props-demo-advanced>
`,
data() {
return {
a: 1,
b: {
name: 'haha'
}
}
},
methods: {
plus() {
console.log(this.a + 1)
},
someMethod() {
console.log("b发生变化了")
}
},
beforeCreate() {
console.log("beforeCreate", "this.$data===", this.$data, "$el=====" , this.$el)
},
created() {
console.log("created", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeMount() {
console.log("beforeMount", "this.$data===", this.$data, "$el=====" , this.$el)
},
mounted() {
console.log("mounted", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeUpdate() {
this.b = {}
console.log("beforeUpdate", "this.$data===", this.$data, "$el=====" , this.$el)
},
updated() {
console.log("update", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeUnmount() {
console.log("beforeDestroy", "this.$data===", this.$data, "$el=====" , this.$el)
},
})
app.use(store).use(router).mount('#app')
在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用。
import { createApp } from 'vue/dist/vue.esm-bundler.js'
// import App from './App.vue'
import router from './router'
import store from './store'
// let app = createApp(App)
let app = createApp({
template: `
<div>在data中监测的数据a -- {{a}}</div>
<div>不在data中监测的数据b --- {{b}}</div>
<props-demo-simple size="16" my-message="hahaja"></props-demo-simple>
<props-demo-advanced :height="100" :age="100"></props-demo-advanced>
`,
data() {
return {
a: 1,
b: {
name: 'haha'
}
}
},
methods: {
plus() {
console.log(this.a + 1)
},
someMethod() {
console.log("b发生变化了")
}
},
beforeCreate() {
console.log("beforeCreate", "this.$data===", this.$data, "$el=====" , this.$el)
},
created() {
console.log("created", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeMount() {
console.log("beforeMount", "this.$data===", this.$data, "$el=====" , this.$el)
},
mounted() {
console.log("mounted", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeUpdate() {
this.b = {}
console.log("beforeUpdate", "this.$data===", this.$data, "$el=====" , this.$el)
},
updated() {
console.log("update", "this.$data===", this.$data, "$el=====" , this.$el)
},
beforeUnmount() {
console.log("beforeDestroy", "this.$data===", this.$data, "$el=====" , this.$el)
},
unmounted() {
console.log("unmounted", "this.$data===", this.$data, "$el=====" , this.$el)
}
})
app.use(store).use(router).mount('#app')
被 keep-alive 缓存的组件激活时调用。
该钩子在服务器端渲染期间不被调用。
被 keep-alive 缓存的组件停用时调用。
该钩子在服务器端渲染期间不被调用。