生命周期钩子函数

浏览 662

课文

这节课我们来详细学习 Vue 实例的生命周期钩子。

生命周期钩子

Vue 实例从被创建出来,就开始经历它的生命周期。在生命周期的过程中,它会提供一些功能,这些功能会在生命周期的每个过渡步骤中执行,以便我们在这些阶段执行某些任务。我们可以把生命周期想象成一个管道,这个管道上面有很多钩子,把我们要做的某些任务钩住。所以这些函数被称为“生命周期钩子(Hook)”。

Vue 总共有 8 个生命周期钩子。每个生命周期阶段都有 2 个钩子,总结如下:

  1. create hook
    • beforeCreate
    • created
  2. mount hook
    • beforeMount
    • mounted
  3. update hook
    • beforeUpdate
    • updated
  4. before hook
    • beforeDestroy
    • destroyed

接下来我们将分别学习每个钩子。

创建 Hook

beforeCreate

beforeCreate 会在在组件初始化时运行。这时 data 和 methods 都没有被挂载到 Vue 实例上。

new Vue({
    el: '#app',
    data: {
    	name: '张三'
    },
    methods: {},
    beforeCreate() {
      console.log(this.name);
    }
})

在上面的示例中,当 beforeCreate 钩子运行时,会在控制台输出 undefined,因为 data 尚未被处理。

created

created 允许访问通过 created 钩子激活的反应数据和事件。这时 template 和虚拟 DOM 还没有被渲染和创建。

<!DOCTYPE html>
<html>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<body>

<div id="app"></div>

<script>
new Vue({
    el: '#app',
  	data: {
      name: '张三'
    },
  	template: '<div>my name is {{ name }}</div>',
    created() {
      const el = document.getElementById('app')
      console.log(el.innerHTML)
    }
})
</script>

</body>
</html>

此时打印的内容是空白的,说明此时 template 并没有被渲染到页面中。

挂载 hook

beforeMount

beforeMount 发生在初始渲染发生之后,需要呈现的内容都已经被编译完成。

new Vue({
    el: '#app',
    beforeMount() {
      console.log('模板已完成渲染')
      console.log('虚拟 DOM 尚未创建:', this.$el)
    }
})

其中 this.$el 是虚拟 DOM 所对应的真实 DOM 的包装对象,此时还没有这个对象,所以是 undefined。

mounted

在 mounted 钩子中,可以完全访问反应式组件、模板和呈现的 DOM(通过this.$el)。

可以在 mounted 中来修改DOM,尤其是在和其它 UI 框架/库集成的时候格外有用。

new Vue({
    el: '#app',
    mounted() {
      console.log('虚拟 DOM 已创建:', Object.keys(this.$el.__vue__).join('\n'))
    }
})

在上面的示例中,我们打印了 this.$el.vue 上面的所有属性。

更新 hook

beforeUpdate

beforeUpdate 钩子在组件上的响应式数据(data)发生变化后运行,这时开始更新。但此时是在修补 DOM 和重新渲染 DOM 之前进行的。

我们可以在 beforeUpdate 中获取组件上的任何响应数据的最新状态。

new Vue({
    el: '#app',
  	data: {
      name: '张三'
    },
  	template: '<div>my name is {{ name }}</div>',
    beforeCreate() {
       setTimeout(() => this.name='李四', 1000)
    },
    beforeUpdate() {
        console.log(this.name);
    }
})

updated

updated 钩子在组件上的数据更新,并且 DOM 重新渲染后运行。

我们可以在属性更新后,在 updated 中根据需要来访问真实的 DOM。

new Vue({
    el: '#app',
  	data: {
      name: '张三'
    },
  	template: '<div id="name">my name is {{ name }}</div>',
    beforeCreate() {
       setTimeout(() => this.name='李四', 1000)
    },
    beforeUpdate() {
        console.log(this.name);
    },
    updated() {
        console.log(document.getElementById('name').innerHTML);
    }
})

销毁 hook

beforeDestroy

beforeDestroy 在组件销毁前执行。这时的组件仍将完全存在并正常运行。

beforeDestroy 非常适合清理事件和一些副作用。

const vm = new Vue({
    el: '#app',
    beforeDestroy() {
        console.log('我马上就要被销毁了!!!');
    }
})

vm.$destroy()

destroyed

组件销毁后,会进入 destroyed 钩子,这时组件上几乎没有任何东西。附着在它上面的一切都被销毁了。

通常我们会在 destroyed 中做一些延迟执行的任务,比如通知服务器,组件已被销毁。

new Vue({
    el: '#app',
    destroyed() {
        console.log('我已经被销毁了!');
    }
})

**恭喜!**🎉🎊 现在您已经掌握了 Vue.js 所有的生命周期钩子。

下面是调用了 Vue 实例所有生命周期钩子的可执行示例。

我已经在每一个生命周期 hook 中通过控制台打印了消息,这样以便你查看钩子的执行顺序。

<!DOCTYPE html>
<html>
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  <body>
    <div id="app"></div>

    <script>
      let vm = new Vue({
        el: "#app",
        data: {
          date: Date()
        },
        template: `<div>
          <h1>这是一个用于观察 Vue.js 生命周期的示例</h1>
          <p>请打开浏览器的控制台观察它们是以什么顺序来执行的。</p>
          <h3>每隔 1 秒会更新时间,所以每隔一秒会执行一次 update hooks。</h3>
          <h3>Vue.js 实例将会在 3 秒后自动销毁,所以 destroy hooks 将会在 3 秒后被执行。</h3>
          <h3>当前时间:{{ this.date }}</h3>
        </div>
        `,
        beforeCreate() {
          console.log("beforeCreate:事件和生命周期已初始化");
        },
        created() {
          console.log("created:Vue 实例已创建");
        },
        beforeMount() {
          console.log("beforeMount:$el 尚未被创建");
        },
        mounted() {
          console.log("mounted:$el 已创建,DOM 已被替换");
        },
        beforeUpdate() {
          console.log("beforeUpdate:虚拟 DOM 尚未被重新渲染和更新");
        },
        updated() {
          console.log("updated:虚拟 DOM 已经被重新渲染和更新");
        },
        beforeDestroy() {
          console.log(
            "beforeDestroy:开始销毁,数据响应式和事件监听尚未被移除"
          );
        },
        destroyed() {
          console.log("destroyed:销毁完毕,数据响应式和事件监听已被移除");
        },
      });

      const timer = setInterval(function () {
        vm.date = new Date()
      }, 1000);

      setTimeout(function () {
        vm.$destroy();
        clearInterval(timer)
      }, 3000);
    </script>
  </body>
</html>

评论

登录参与讨论

暂无评论

共 0 条
  • 1
前往
  • 1