Skip to content

类组件支持几乎全部 Vuejs 原生生命周期钩子函数,钩子函数在类组件中同样使用类方法来表示,也就是说钩子函数是一组特殊的类方法。

内置钩子函数

钩子函数执行时机
beforeCreate在组件实例初始化完成之后立即调用
created在组件实例处理完所有与状态相关的选项后调用
beforeMount在组件被挂载之前调用
mounted在组件被挂载之后调用
beforeUpdate在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用
updated在组件因为一个响应式状态变更而更新其 DOM 树之后调用
activated若组件实例是 [<KeepAlive>](https://cn.vuejs.org/api/built-in-components.html#keepalive) 缓存树的一部分,当组件被插入到 DOM 中时调用。
deactivated若组件实例是 [<KeepAlive>](https://cn.vuejs.org/api/built-in-components.html#keepalive) 缓存树的一部分,,当组件从 DOM 中被移除时调用
beforeDestroy实例销毁之前调用。在这一步,实例仍然完全可用。
beforeUnmount在一个组件实例被卸载之前调用
destroyed实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
unmounted在一个组件实例被卸载之后调用
renderTracked在一个响应式依赖被组件的渲染作用追踪后调用(仅在开发模式下可用
renderTriggered在一个响应式依赖被组件触发了重新渲染之后调用(仅在开发模式下可用
serverPrefetch当组件实例在服务器上被渲染之前要完成的异步函数
render

通过在 App 组件中动态切换组件来观察组件钩子函数的打印情况。

vue
<script lang="ts">
import { Component, Vue } from 'vue-facing-decorator';

@Component({
  name: 'MyComponent',
})
export default class MyComponent extends Vue{
  beforeCreate(){
    console.log('beforeCreate 组件初始化完成')
  }
  created() {
    console.log('created 组件实例状态初始化完毕')
  }
  beforeMount(){
    console.log('beforeMount 组件开始被挂载')
  }
  mounted(){
    console.log('mounted 组件被挂载完毕')
  }
  beforeUnmount(){
    console.log('beforeUnmount 实例开始被卸载')
  }
  unmounted(){
    console.log('unmounted 实例被卸载完毕')
  }
}
</script>

<template>
  <div>Hello World</div>
</template>
vue
<script lang="ts">
import MyComponent from './components/MyComponent.vue';
import {Component, Vue} from 'vue-facing-decorator';
@Component({
  name: 'App',
  components: {
    MyComponent,
  }
})
export default class App extends Vue {
  isLoading = false;

  changeStatus() {
    this.isLoading = !this.isLoading;
  }
}
</script>

<template>
  <button @click="changeStatus">{{ isLoading ? '卸载组件' : '加载组件'}}</button>
  <MyComponent v-if="isLoading">
</template>

下面是引用自 Vuejs 网站的组件的生命周期图:

组件生命周期图示

其它钩子函数

除内置的钩子提供直接使用以外,往往在使用 Vuejs 全家桶其他的模块时,也会需要用到各种各种的钩子函数,这个时候就需要用到一个新的装饰器:@Hook,通过 @Hook 装饰器来描述对应的方法是一个钩子函数。

配置组件及 router 对象:

typescript
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
import * as VueRouter from 'vue-router';

const routes = [
  { path: '/', component: () => import('./components/Home.vue') },
  { path: '/about', component: () => import('./components/About.vue') },
];

const router = VueRouter.createRouter({
  history: VueRouter.createWebHashHistory(),
  routes,
});

createApp(App)
  .use(router)
  .mount('#app');

配置 App 模板:

vue
<template>
  <div>
   <p>
      <router-link to="/">Go to Home</router-link>
      <router-link to="/about">Go to About</router-link>
    </p>
    <router-view></router-view>
  </div>
</template>

Home 组件中使用 router 相关钩子函数:

vue
<script lang="ts">
import {Component, Hook, Vue} from 'vue-facing-decorator'
@Component({
  name: 'Home'
})
export default class Home extends Vue {

  @Hook
  beforeRouteEnter(to, from) {
    console.log('在渲染该组件的对应路由被验证前调用')
  }

  @Hook
  beforeRouteLeave(to, from) {
    console.log('在导航离开渲染该组件的对应路由时调用')
  }
}
</script>

<template>
  Home
</template>