基本生命周期
vue 是 _ 单向数据流 _,也就是数据总是从父组件传递到子组件中,子组件无权修改父组件中的数据。因为当父组件 可能存在多个子组件,假如子组件可以修改父组件的数据,那么会导致其他依赖父组件的子组件都会受到影响
Vue 实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程,称这是Vue的⽣命周期。
- beforeCreate(创建前):数据观测和初始化事件还未开始,此时 data 的响应式追踪、event/watcher 都还没有被设置,也就是说不能访问到data、computed、watch、methods上的方法和数据。
- created****(创建后) :实例创建完成,实例上配置的 options 包括 data、computed、watch、methods 等都配置完成,但是此时渲染得节点还未挂载到 DOM,所以不能访问到
$el属性。 - beforeMount(挂载前):在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。此时还没有挂载html到页面上。
- mounted(挂载后):在el被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html 页面中。此过程中进行ajax交互。
- beforeUpdate(更新前):响应式数据更新时调用,此时虽然响应式数据更新了,但是对应的真实 DOM 还没有被渲染。
- updated(更新后) :在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。此时 DOM 已经根据响应式数据的变化更新了。调用时,组件 DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
- beforeDestroy(销毁前):实例销毁之前调用。这一步,实例仍然完全可用,
this仍能获取到实例。 - destroyed(销毁后):实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务端渲染期间不被调用。
现在补充下这几个 不寻常 钩子
activaed 和 deactivated
activated:被 keep-alive 缓存的组件激活时调用
deactivated:被 keep-alive 缓存的组件失活时调用
这两个钩子需在 keep-alive 标签包裹的内容中使用,keep-alive 使用具体参看 内置组件 keep-alive | Vue.js
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>activated() {
console.log("1激活activated钩子函数");
}
deactivated() {
console.log("2激活deactivated钩子函数");
}注意
vue 文档中有提到这两个钩子在服务端渲染期间不被调用
换个思路理解,这两个钩子,与其他钩子对比,也就是位于 mounted 后,beforeUpdated前 调用
如< keep-alive >包裹两个组件:组件 A 和组件 B
- 当第一次切换到组件 A 时,组件 A 的 created 和 activated 生命周期函数都会被执行,这时通过点击事件改变组件 A 的文字的颜色,在切换到组件 B,这时组件 A 的 deactivated 的生命周期函数会被触发
- 在切换回组件 A,组件 A 的 activated 生命周期函数会被触发,但是它的 created 生命周期函数不会被触发了,而且 A 组件的文字颜色也是我们之前设置过的
errorCaptured
在捕获一个来自后代组件的错误时被调用
此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播
(err: Error, instance: Component, info: string) => ?boolean错误传播规则
- 默认情况下,如果全局的 config.errorHandler 被定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报。
- 如果一个组件的继承链或父级链中存在多个 errorCaptured 钩子,则它们将会被相同的错误逐个唤起。
- 如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 config.errorHandler。
- 一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说 " 这个错误已经被搞定了且应该被忽略 "。它会阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler
renderCaptured 和 renderTriggered
renderCaptured:直译过来就是状态跟踪,它会跟踪页面上所有响应式变量和方法的状态,也就是我们用 return 返回去的值,它都会跟踪。只要页面有 update 的情况,它就会跟踪,然后生成一个 event 对象,我们通过 event 对象来查找程序的问题所在(初始渲染时会调用 renderTracked)
renderTriggered: 直译过来是状态触发,它不会跟踪每一个值,而是给你变化值的信息,并且新值和旧值都会给你明确的展示出来
<div id="app">
<button v-on:click="addToCart">Add to cart</button>
<p>Cart({{ cart }})</p>
</div>const app = createApp({
data() {
return {
cart: 0
}
},
renderTracked({ key, target, type }) {
console.log({ key, target, type })
/* 当组件第一次渲染时,这将被记录下来:
{
key: "cart",
target: {
cart: 0
},
type: "get"
}
*/
},
renderTriggered({ key, target, type }) {
console.log({ key, target, type })
/*
{
key: "cart",
target: {
cart: 1
},
type: "set"
}
*/
},
methods: {
addToCart() {
this.cart += 1 // 这将导致 renderTriggered 被调用
}
}
})
app.mount('#app')