Tìm hiểu về Lifecycle Hooks trong Vuejs

Lifecycle hooks: cho phép bạn hiểu khi nào thì component được create, add to the DOM, updated, destroyed.

Đây là hình ảnh từ Vue.js documentation cho thấy được vòng đời của một Vue Instance.

Mình sẽ chia ra 4 cặp Hooks thông dụng để các bạn có thể ghi nhớ dễ dàng hơn:

  1. beforeCreate vs created
  2. beforeMount vs mounted
  3. beforeUpdate vs updated
  4. beforeDestroy vs destroyed

Hay cùng mình đi qua từng cặp Hooks và những ví dụ để hiểu cách hoạt động của nó như thế nào.

1. beforeCreate vs created

  • beforeCreate:
    • chạy trước khi render
    • được gọi synchronously (đồng bộ) ngay sau khi instance đã được khởi tạo
    • datamethods chưa khởi tạo nên không thể lấy được ở giai đoạn này.
<template>
  <div>{{ text }}</div>
</template>

<script>
export default {
  components: {},
  beforeCreate() {
    console.log("Opion/LifeCycle -> beforeCreate", this.text);
    this.foo();
  },

  data() {
    return {
      text: "Lifecycle",
    };
  },

  methods: {
    foo() {
      console.log("methods -> foo");
    },
  },
};
</script>

Kết quả:


  • created:
    • chạy trước khi render
    • Chạy sau khi beforeCreate chạy xong.
    • datamethodsđã được tạo nên có thể lấy được ở giai đoạn này.
    • $el (root DOM elementVue instance đang quản lý) chưa có vì chưa được mount
<template>
  <div>{{ text }}</div>
</template>

<script>
export default {
  components: {},
  beforeCreate() {
    console.log("Opion/LifeCycle -> beforeCreate", this.text);
    // this.foo();
  },

  data() {
    return {
      text: "Lifecycle",
    };
  },

  methods: {
    foo() {
      console.log("methods -> foo");
    },
  },

  created() {
    console.log("Opion/LifeCycle -> created", this.text);
    console.log("$el", this.$el);
    this.foo();
  },
};
</script>

Kết quả:

2. beforeMount vs mounted

  • beforeMount

    • Chạy sau khi created chạy xong
    • Chuẩn bị việc mounting
  • mounted

    • Chạy sau khi việc mounting đã kết thúc.
    • $el: thằng này ở created chưa thể lấy được nhưng ở mounted thì đã có kết quả như hình.
    • Note: Ở giai đoạn này chưa hẳn tất cả component đã được mounted. Nếu bạn muốn đợi cho tất cả được render thì có thể tìm hiểu thêm về thằng vm.$nextTick trong mounted.

Ví dụ:

<script>
export default {
  components: {},
  data() {
    return {
      text: "Lifecycle",
    };
  },
  beforeMount() {
    console.log("Option/Lifecycle beforeMount");
  },
  /*
    Bạn có thể xóa phần tag template phía trên và thay vào phần render function ở dưới sẽ thấy được
    quá trình render giữa 2 Hook.
  */
  render: function (createElement) {
    console.log("render");
    return createElement("div", this.text);
  },
  mounted() {
    console.log("Option/Lifecycle mounted");
    console.log("this.$el", this.$el);
  },
};
</script>
</script>

Kết quả:

3. beforeUpdate vs updated

Quay lại hình ở phía trên, chúng ta có thể thấy được khi có những sự thay đổi data thì cặp Hook này sẽ chạy:

  • beforeUpdate
    • Gọi khi data thay đổi và trước khi DOM được patch.
    • Lấy dữ liệu DOM cũ trước khi thay đổi DOM mới
  • updated
    • Được gọi sau khi dữ liệu thay đổi làm cho DOM được re-render and patch.
    • Hạn chế change data ở Hook này, thay vì thế sử dụng computed hoặc watcher thay thế.
    • Giống như mounted: giai đoạn này chưa hẳn tất cả component đã được re-render. Nếu bạn muốn đợi cho tất cả được re-render thì có thể tìm hiểu thêm về thằng vm.$nextTick trong updated

Ví dụ: Tạo một text và một button, sau khi render lần đầu thì click vào button

<script>
export default {
  components: {},
  data() {
    return {
      text: "Lifecycle",
    };
  },

  methods: {
    updateText() {
      this.text = "Lifecycle-Updated";
    },
  },

  beforeUpdate() {
    console.log("Option/Lifecycle beforeUpdate");
  },

  render: function (createElement) {
    console.log("render");

    return createElement("div", [
      this.text,
      createElement(
        "button",
        {
          on: {
            click: this.updateText,
          },
        },
        "Update Text"
      ),
    ]);
  },

  updated() {
    console.log("Option/Lifecycle updated");
  },
};
</script>

Kết quả:

4. beforeDestroy vs destroyed

  • beforeDestroy: Được gọi trước khi instance được destroy. Ở giai đoạn này, instance vẫn có đủ các chức năng.

  • destroyed: được gọi sau khi instance đã được destroy. Khi hooks này được gọi, tất cả directives của instance đều được unbound, tất cả event listerner đều đã được removed, và tất cả con của cũng được destroy.

Vi dụ:

// index.vue
<template>
  <div>
    <ComponentText v-if="isShow" />
    <button @click="toggleShow">isShow: {{ isShow }}</button>
  </div>
</template>

<script>
import ComponentText from "./ComponentText";

export default {
  components: { ComponentText },
  data() {
    return {
      text: "Lifecycle",
      isShow: true,
    };
  },

  methods: {
    toggleShow() {
      this.isShow = !this.isShow;
    },
  },
};
</script>
// ComponentText.vue
<template>
  <p>Text</p>
</template>

<script>
export default {
  beforeDestroy() {
    console.log("Option/Lifecycle beforeDestroy");
  },

  destroyed() {
    console.log("Option/Lifecycle destroyed");
  },
};
</script>

<style>
</style>

Kết quả: khi click vào button

Mong rằng sau khi đọc bài viết này, dựa vào những khái niệm cơ bản, các bạn có thể tự mình sáng tạo, linh hoạt hơn trong khi làm dự án của bạn.

Nếu thấy không hiểu hoặc có những góp ý cho bài viết thì mong các bạn để lại comment nhé [email protected]#$%^&*


All Rights Reserved