Vue.js 3: So sánh Options API và Composition API

5 min read

Vue.js 3 So sánh Options API và Composition API

Khi làm việc với Vue 3, bạn sẽ nhận thấy rằng framework này hỗ trợ hai cách để xây dựng thành phần (component): cách truyền thống được gọi là Options API, và cách hiện đại hơn là Composition API. Vậy tại sao Vue lại có hai phong cách này? Và trong thực tế, nên chọn cách nào cho dự án của bạn? Mình sẽ cùng bạn tìm hiểu chi tiết bên dưới.

Vì sao Vue lại hỗ trợ hai cách viết component?

Ban đầu, Vue được sinh ra với mục tiêu là một thư viện nhẹ, dễ học và dễ dùng để xây dựng giao diện tương tác – so với những framework lớn hơn như Angular hay những cách tiếp cận “khá nặng” khác, Vue nổi bật vì sự đơn giản. Trong giai đoạn đó, Options API rất phù hợp: bạn có các khối như data, methods, computed, watch… đặt mọi thứ vào đúng chỗ – giúp cho cú pháp trực quan và dễ hiểu.

Tuy nhiên, khi ứng dụng ngày càng lớn và phức tạp hơn, cấu trúc này bắt đầu bộc lộ hạn chế: logic bị phân tán, nếu một component có nhiều chức năng thì các phần data, methods, computed bị tách rời và khó theo dõi. Chính vì vậy, Vue 3 đã giới thiệu Composition API – nhằm giúp bạn tổ chức logic theo “chức năng” hơn là theo “khối tùy chọn”, cải thiện khả năng tái sử dụng và bảo trì code.

Tóm lại: Options API vẫn giữ vai trò quan trọng vì tính dễ học, dễ tiếp cận; Composition API xuất hiện để xử lý những dự án lớn hơn, với yêu cầu linh hoạt và tái sử dụng cao hơn.

Minh họa: Một component viết bằng Options API và viết bằng Composition API

Để rõ hơn, mình sẽ dùng ví dụ rất đơn giản: một danh sách To-Do.

Viết bằng Options API

<template>
  <h3>My To-Do List</h3>
  <div>
    <input v-model="newItemText" @keyup.enter="addNewTodo" />
    <button @click="addNewTodo">Add</button>
    <button @click="removeTodo">Remove</button>
    <button @click="removeAllTodos">Remove All</button>
    <transition-group name="list" tag="ul">
      <li v-for="task in tasks" :key="task">{{ task }}</li>
    </transition-group>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tasks: ["Write my posts", "Go for a walk", "Meet my friends", "Buy fruit"],
      newItemText: ""
    };
  },
  methods: {
    addNewTodo() {
      if (this.newItemText !== "") {
        this.tasks.unshift(this.newItemText);
      }
      this.newItemText = "";
    },
    removeTodo() {
      this.tasks.pop();
    },
    removeAllTodos() {
      this.tasks = [];
    }
  }
};
</script>

<style>
/* … style cho đẹp … */
</style>

Ở đây bạn sẽ thấy rõ: data dùng để khai báo trạng thái, methods chứa hàm xử lý, template liên kết với chúng thông qua this. Rõ ràng, dễ hiểu và rất phù hợp với người mới bắt đầu.

Viết bằng Composition API

<script>
import { ref } from 'vue';

export default {
  setup() {
    const tasks = ref(["Write my posts", "Go for a walk", "Meet my friends", "Buy fruit"]);
    const newItemText = ref("");

    function addNewTodo() {
      if (newItemText.value !== "") {
        tasks.value.unshift(newItemText.value);
      }
      newItemText.value = "";
    }

    function removeTodo() {
      tasks.value.pop();
    }

    function removeAllTodos() {
      tasks.value = [];
    }

    return {
      tasks,
      newItemText,
      addNewTodo,
      removeTodo,
      removeAllTodos
    };
  }
};
</script>

Như bạn thấy: mọi logic được đặt trong hàm setup(). Biến được tạo bằng ref, hàm xử lý logic và cuối cùng return các biến/hàm cần dùng trong template. Phong cách này giúp chúng ta gom nhóm logic liên quan gần nhau, dễ tái sử dụng hơn.

So sánh khả năng tái sử dụng giữa hai API

Một trong những lý do lớn để chuyển sang Composition API là khả năng tái sử dụng logic (reusability) – ứng dụng lớn thường có nhiều phần logic giống nhau hoặc có thể tách riêng thành các “gói” nhỏ hơn để sử dụng lại.

Với Options API, cách phổ biến là dùng mixin. Ví dụ bạn có một mixin đếm số lần:

export default {
  data() { return { count: 0 } },
  methods: {
    increment() { this.count++ },
    reset() { this.count = 0 }
  }
}

Sau đó trong component bạn import mixin và sử dụng. Tuy nhiên, mixin có một số hạn chế: khó truyền tham số, dễ trùng tên, không rõ nguồn gốc của data/hàm mixin khi nhiều mixin cùng dùng.

Với Composition API, bạn có thể tạo composable — một hàm tự do (function) chứa logic tái sử dụng, rồi import vào nhiều component. Ví dụ:

// useCounter.js
import { ref, readonly } from 'vue';

export default function useCounter(initial = 0) {
  const count = ref(initial);
  const increment = () => { count.value += 1 };
  const reset = () => { count.value = 0 };

  return {
    count: readonly(count),
    increment,
    reset
  };
}

Sau đó trong component:

import useCounter from './useCounter';

setup() {
  const { count, increment, reset } = useCounter(5);
  // …
  return { count, increment, reset };
}

Ưu điểm: rõ ràng nguồn gốc logic, tránh trùng tên, dễ bảo trì và test.

Khi nào nên dùng Options API và khi nào nên dùng Composition API?

Đây là một số lời khuyên giúp bạn lựa chọn:

  • Nếu dự án nhỏ, đơn giản, không có quá nhiều logic lồng nhau hoặc không cần tái sử dụng cực lớn – thì Options API là lựa chọn nhanh, dễ hiểu, dễ bàn giao.
  • Nếu ứng dụng lớn, logic phức tạp, nhiều module/chức năng cần tái sử dụng và bạn muốn quản lý tốt hơn – thì Composition API sẽ phù hợp hơn.
  • Lưu ý rằng bạn không bắt buộc chuyển toàn bộ dự án sang Composition từ đầu – bạn có thể bắt đầu với Options API và khi cần thì dùng Composition cho những component lớn hơn hoặc logic tái sử dụng.

Dưới đây là bảng so sánh nhanh:

Yếu tốComposition APIOptions API
Phù hợp vớiỨng dụng trung – lớn, nhiều logic, tái sử dụng caoỨng dụng nhỏ hoặc mô-đun riêng lẻ đơn giản
Cách tổ chức logicTheo chức năng, nhóm logic liên quan với nhauTheo khối data, methods, computed, …
Khả năng tái sử dụng logicCao, via composablesThấp hơn, thường dùng mixins
Hỗ trợ TypeScriptRất tốtTương thích nhưng hơi hạn chế hơn
Đường cong học tậpCao hơn (đòi hỏi hiểu ref, reactive, setup)Thấp hơn, quen thuộc với người mới Vue

Kết luận

Hai phong cách – Options API và Composition API – đều có chỗ đứng riêng trong hệ sinh thái Vue. Việc lựa chọn không phải là “cách nào tốt hơn hoàn toàn”, mà là “cách nào phù hợp hơn với dự án và nhóm phát triển của bạn”.

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *