Skip to content

VueCore – Tìm hiểu Composition Vue 3

Composition là một tính năng hoàn toàn mới giúp cải thiện đáng kể về cách mà chúng ta phân phối code hay còn gọi là refactor đó

Đối với Vue 2 thì ta sử dụng Option API

Composition API RFC | Vue Composition API

Với Option API thì code của ta hoàn toàn bị phân mảnh –> khó quản lý

Sẽ có 1 bài biết khác nói về lý do sử dụng Composition thay vì Option API (need update)

Nhưng trong bài viết này hãy cùng tìm hiểu cách để sử dụng tính năng mới của Vue 3 nhé


Contents

    Điều đầu tiên cần biết

    Compositon API is Optional

    Nếu bạn chuyển từ Vue 2 sang 3 thì không nhất thiết bạn cứ phải ứng dụng Composition mà bỏ đi Option API. Bạn hoàn toàn có thể sử dụng lại Option API một cách bình thường và Composition là một lựa chọn thêm thôi

    data() vs setup()

    Ở vue 2 chúng ta sử dụng data() nhưng không thể sử dụng Async được

    async data() {
        let content = await axios.get({...});
        return {
          content: "trung thinh"
        }
    }

    Đây là kết quả !

    Chính vì thế ta đổi qua và sử dụng setup()

    <template>
        <h1>{{ mock.data.title }}</h1>
    </template>
    
    <script>
    import axios from 'axios'
    import { reactive } from 'vue'
    
    export default {
      async setup() {
        const mock = await reactive(axios.get('https://jsonplaceholder.typicode.com/todos/1'))
    
        console.log(mock)
    
        return {
          mock
        };
      }
    }
    </script>
    
    // MyCmp.vue
    Lưu ý là phải bắt buộc phải bỏ Async Code --> vào 1 Child Component mới hoạt động được

    Bỏ thẳng trực tiếp lên App.vue thì không tài nào chạy nổi nhé

    <template>
      <Suspense>
        <template #default>
          <MyCmp></MyCmp>
        </template>
        <template #fallback>
          loading...
        </template>
      </Suspense>
    </template>
    
    <script>
    import MyCmp from '@/components/MyCmp.vue';
    
    export default {
      components: {
        MyCmp
      }
    }
    </script>
    
    // App.vue

    Giải thích sơ qua về <Suspense> là cái để hiển thị loader . . . nhưng mà giải thích như vậy thì đơn giản quá ! Tác dụng thực sự của nó mới khiến bạn thốt lên “quàoooo” thật sao

    suspense vuejs
    <Suspense>

    Hiểu <Suspense> trong 4 phút 30 giây với Vue Mastery

    Lifecycle

    setup() sẽ được chạy trước tất cả

    • components
    • props
    • data
    • methods
    • computed
    • lifecycle methods
    Chính vì được khởi tạo trước cả mounted() nên sẽ không thể sử dụng "this" bên trong setup()

    Param

    setup() method nhận 2 param : props (1st), context(2nd)

    context param và những prop đi kèm

    ref, reactive là gì ?

    Ở vue 2, ta không cần hiểu về khái niệm này ! Vì tất cả những giá trị đặt trong data() đều có tính năng reactive

    Reactive là cái lý do mà bạn sử dụng VueJs đó :))) Là khi bạn thay đổi "content: ___"<input> thì nó sẽ thay đổi ở <h1> luôn

    Đó chính là Reactive ! Quen mà đúng k 🙂

    Nhưng mà ở Composition API, những giá trị trong setup() không tự động có thuộc tính reactive mà ta cần phải bọc những giá trị với 1 Wrapper

    2 dạng wrapper :

    • ref() : dùng cho Primitive Type
      • String
      • Number
      • BigInt
      • Boolean
      • Symbol
      • Null
      • Undefined
    • reactive() : dùng cho object
      • khi sử dụng reactive() thì ~ key – value đặt trong nó sẽ có thuộc tính

    Sử dụng ref()

    <template>
      <h1>{{ content }}</h1>
    </template>
    
    <script>
    import { ref } from 'vue'
    export default {
      setup() {
        const content = ref("Trung Thinh");
    
        // change content 
        content.value = "Not Trung Thinh"
        return {
          content
        }
      }
    }
    </script>

    ref() là 1 wrapper bao bọc value “Trung Thinh” –> Chính vì thế để thay đổi hay truy cập giá trị –> Sử dụng .value

    Ở <template> không sử dụng .value vì cơ chế auto-unwrap của Vue

    Thử log ref xem nào !

    const content = ref("Trung Thinh");
    
    console.log(content);

    kết quả :

    kết quả wrapper ref()

    Sử dụng reactive()

    <template>
      <h1>{{ content.name }}</h1>
    </template>
    
    <script>
    import { reactive } from 'vue'
    export default {
      setup() {
        const content = reactive({
          name: "Trung Thinh"
        });
    
        console.log(content);
        // change content 
        content.name = "Not Trung Thinh"
        return {
          content
        }
      }
    }
    </script>

    Với reactive() thì hoàn toàn khác ! Không sử dụng .value mà thay vào đó là tên key

    Thử console.log reactive() xem ?

    const content = reactive({
       name: "Trung Thinh"
    });
    
    console.log(content);
    
    Kết quả

    Proxy ? Đúng Vue 3 đã ứng dụng Proxy

    Hiểu Vue 3 Proxy chỉ trong 9 phút cùng Vue Mastery

    Destructure

    Ta có thể biến reactive values –> thành nhiều ref –> không cần phải gọi wrapper name ở <template> bằng cách sử dụng toRefs

    dùng toRefs thay vì ...event vì dùng “chay” như vậy sẽ mất đi sự reactivity của nó

    Sử dụng Lifecycle bên trong setup()

    Gồm 9 lifecycles này :

    • onBeforeMount
    • onMouted
    • onBeforeUpdate
    • onUpdated
    • onBeforeUnmount
    • onUnmount
    • onActivated
    • onDeactivated
    • onErrorCaptured
    • onRenderTracked
    • onRenderTriggered
    lifecycle trong setup()

    Chính cách gọi như thế này giúp ta dễ tách code thành nhiều module (composable) khác nhau

    Nếu để ý sẽ không thấy beforeCreate() & create()

    setup() nằm giữa 2 giai đoạn này

    => Nên việc thêm 2 lifecycle này là không cần thiết

    2 Lifecycles mới

    Sử dụng computed, watch & watchEffect

    <template>
      <h1>{{ finalContent }}</h1>
    </template>
    
    <script>
    import { ref } from 'vue'
    export default {
      setup() {
        const content = ref("Trung Thinh");
    
        const finalContent = "Tên tôi là : " + content.value;
        // change content 
        content.value = "Not Trung Thinh"
        return {
          finalContent
        }
      }
    }
    </script>

    Ở trên tôi đã thay đổi content.value = ‘Not Trung Thinh’

    Tại sao kết quả lại như thế này ?

    not using computed

    Tìm hiểu thêm ở đây……

    Tóm lại

    Chúng ta đã hiểu được sự khác biệt giữa Option API & Composition API. Cũng như hiểu sơ qua về cấu trúc của Composion

    Ref là gì ? Reactive là gì? . . . và còn Computed(), watch(), watchEffect() sẽ được viết trong bài khác

    Bạn Composition API có tiện hơn Option API không ?

    Theo tôi thấy Composition API khó hiểu hơn ! Nó phức tạp hơn nhưng nếu bạn muốn làm một ứng dụng mà có thể scale up –> sử dụng Composition API ngay từ đầu

    Bạn nghĩ cái nào tiện hơn ?

    Published inDành cho mọi ngườiVue Core

    Be First to Comment

    Leave a Reply

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