const props = defineProps({
count: {
type: Number, // kiểu hoặc mảng chứa kiểu của prop
required: false, // true or false
default: 10, // giá trị mặc định khi không truyền prop
},
});
a)
Khi định nghĩa thì đặt tên theo quy tắc camelCase
defineProps({
greetingMessage: String,
});
Khi truyền prop thì gọi theo quy tắc kebab-case
<MyComponent greeting-message="hello" />
b) Với kiểu string thì có thể binding tĩnh
<BlogPost title="My journey with Vue" />
Các kiểu còn lại truyền vào prop phải dùng v-bind
hoặc :
<!-- kiểu number -->
<BlogPost :likes="42" />
<!-- kiểu boolean -->
<BlogPost is-published />
<BlogPost :is-published="false" />
- B1: Định nghĩa và emit sự kiện ở
MyComponent.vue
:
const emits = defineEmits(['inFocus', 'submit']);
function buttonClick() {
emit('submit');
}
<button @click="buttonClick">Click me to submit</button>
- B2: Ở component cha có thể lắng nghe sự kiên mà
MyComponent
emit lên
<MyComponent
@in-focus="callbackFocus"
@submit="callbackSubmit"
/>
Khi emit sự kiện ở component con, ngoài đối số đầu tiên là tên sự kiện, nếu ta tryền vào 1 hay nhiều đối số nữa thì ở component cha có thể lấy được đối số đó bằng cách sử dụng tham số ở callback lắng nghe
- Ở
MyButton.vue
:
<button @click="emits('eventame', 1, 2, 3)">
Kích để truyền 1, 2, 3 lên component cha
</button>
- Khi sử dụng
MyButton
component:
<MyButton
@event-name="(p1, p2, p3) => {
console.log(p1, p2, p3);
}"
/>
Từ Vue 3.4 trở đi, các component hoàn toàn có thể nhanh chóng tạo cho nó 1 hoặc nhiều props Two-way Data Flow, gọi là model
- Ở
MyComponent.vue
:
const model = defineModel({
type: Number,
required: false,
default: 100,
});
function update() {
model.value++;
}
- Sử dụng:
const count = ref(0);
<MyComponent v-model="count" />
- Khai báo sẽ đặt tên cho model
const usernameModel = defineModel('username', {
type: String,
required: false,
default: '',
});
- Khi sử dụng sẽ dụng
directives
v-model:[modelName]
<MyComponent v-model:username="username" />
- Template của
FancyButton.vue
<button class="fancy-btn">
<!-- slot outlet -->
<slot></slot>
</button>
- Khi sử dụng, những content ở giữa sẽ được thay thế và đặt vào vị trí
slot
<FancyButton>
<!-- slot content -->
Click me!
</FancyButton>
Chúng ta có thể hiển thị 1 giao diện dự phòng khi có slot outlet
nhưng không có slot content
<button class="fancy-btn">
<!-- slot outlet -->
<slot>
<!-- fallback content -->
Fancy button
</slot>
</button>
Nếu có trên 2 slot thì chúng ta phải đặt tên cho các slot
- Ở
BaseLayout.vue
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
- Khi sử dụng:
<BaseLayout>
<template #header>
<!-- content for the header slot -->
</template>
<!-- content for the default slot -->
<div>Main content</div>
<template #footer>
<!-- content for the header slot -->
</template>
</BaseLayout>
Những slot content
không đặt trong template
hoặc được đặt trong <teamplate #default></teamplate>
thì sẽ replace vào slot
không có name.
Sử dụng Scoped Slots
để có thể truyền dữ liệu từ Slot outlet
lên Slot content
<!-- <MyComponent> template -->
<div>
<!-- scoped slot outlet -->
<slot
:text="greetingMessage"
:count="1"
></slot>
</div>
<MyComponent>
<!-- scoped slot content -->
<template #default="{ text, count }">
<div>
<p>{{ text }}</p>
<span>{{ count }}</span>
</div>
</template>
</MyComponent>
Giải quyết được vấn đề truyền props qua nhiều tầng, mà các tầng trung gian không cần thiết
Chúng ta dùng provide
để cung cấp 1 value
thông qua key
cho tất cả các component thuộc component mà sử dụng provide
import { provide, ref } from 'vue';
provide(/* key */ 'message', /* value */ 'hello!');
const count = ref(0);
provide('count', count);
Chúng ta sử dụng inject
để lấy value
thông qua key
mà những component chứa component mà sử dụng inject
đã provide
import { inject } from 'vue';
const message = inject('message');