生命周期

每个 Vue 实例都有一个完整的生命周期:从创建、挂载、更新到销毁。在这个过程中,Vue 提供了一系列钩子函数,让你可以在特定阶段执行代码。

理解生命周期是深入 Vue 的关键。它解释了组件什么时候初始化数据、什么时候可以访问 DOM、什么时候应该清理资源。

什么是生命周期

生命周期是 Vue 实例从诞生到消亡的完整过程。就像人的生老病死,Vue 实例也经历着:

创建 → 挂载 → 更新 → 销毁

每个阶段都有对应的钩子函数:

阶段钩子函数说明
创建beforeCreate, created实例初始化
挂载beforeMount, mountedDOM 渲染
更新beforeUpdate, updated数据变化
销毁beforeDestroy, destroyed实例销毁

为什么需要生命周期钩子

生命周期钩子让你能够:

1. 初始化时机控制

new Vue({
  data: {
    users: []
  },
  created() {
    this.fetchUsers()
  },
  methods: {
    async fetchUsers() {
      const response = await fetch('/api/users')
      this.users = await response.json()
    }
  }
})

2. DOM 操作时机

new Vue({
  mounted() {
    this.initChart()
  },
  methods: {
    initChart() {
      const canvas = this.$refs.canvas
      new Chart(canvas, this.chartConfig)
    }
  }
})

3. 资源清理

new Vue({
  data() {
    return {
      timer: null
    }
  },
  mounted() {
    this.timer = setInterval(() => {
      this.refresh()
    }, 5000)
  },
  beforeDestroy() {
    clearInterval(this.timer)
  }
})

生命周期钩子分类

Vue 的生命周期钩子可以分为四类:

创建阶段钩子

创建阶段是实例初始化的过程,此时还没有开始渲染 DOM。

new Vue({
  beforeCreate() {
    console.log('实例初始化之前')
    console.log(this.message)
  },
  created() {
    console.log('实例创建完成')
    console.log(this.message)
  },
  data: {
    message: 'Hello'
  }
})

挂载阶段钩子

挂载阶段将模板渲染成 DOM。

new Vue({
  beforeMount() {
    console.log('挂载之前')
    console.log(this.$el)
  },
  mounted() {
    console.log('挂载完成')
    console.log(this.$el)
  }
})

更新阶段钩子

当数据变化时触发更新阶段。

new Vue({
  beforeUpdate() {
    console.log('数据变化,DOM 更新之前')
  },
  updated() {
    console.log('DOM 更新完成')
  }
})

销毁阶段钩子

实例销毁时触发。

new Vue({
  beforeDestroy() {
    console.log('实例即将销毁')
  },
  destroyed() {
    console.log('实例已销毁')
  }
})

生命周期与组件

组件同样拥有完整的生命周期:

Vue.component('my-component', {
  template: '<div>{{ message }}</div>',
  data() {
    return {
      message: 'Hello'
    }
  },
  created() {
    console.log('组件创建')
  },
  mounted() {
    console.log('组件挂载')
  },
  beforeDestroy() {
    console.log('组件即将销毁')
  }
})

组件的生命周期与实例的生命周期遵循相同的规则。

特殊情况

keep-alive 组件

被 keep-alive 缓存的组件有额外的钩子:

Vue.component('cached-component', {
  template: '<div>内容</div>',
  activated() {
    console.log('组件被激活')
  },
  deactivated() {
    console.log('组件被缓存')
  }
})

错误捕获

Vue 提供了错误捕获钩子:

new Vue({
  errorCaptured(err, vm, info) {
    console.error('捕获到错误:', err)
    console.error('错误来源:', info)
    return false
  }
})

生命周期最佳实践

1. 数据请求放在 created

created() {
  this.loadData()
}

created 钩子在服务端渲染时也会执行,更适合数据初始化。

2. DOM 操作放在 mounted

mounted() {
  this.$nextTick(() => {
    this.initThirdPartyLibrary()
  })
}

3. 清理工作放在 beforeDestroy

beforeDestroy() {
  this.eventBus.$off('event', this.handler)
  window.removeEventListener('resize', this.handleResize)
}

4. 避免在 updated 中修改数据

updated() {
  this.counter++
}

这会导致无限循环。