父子組件進行數據雙向綁定 - daniel-qa/Vue GitHub Wiki
在 Vue 3 中,defineProps 和 defineEmits 是兩個非常重要的 API,它們主要用於父子組件之間的溝通。
作用: 用於在子組件中聲明 props,props 是父組件傳遞給子組件的數據。
使用方式: 在 <script setup> 語法糖中,直接使用 defineProps() 函數。
參數: 可以是一個物件,也可以是一個泛型。
- 範例一:物件形式
<template>
<div>
<p>姓名:{{ name }}</p>
<p>年齡:{{ age }}</p>
</div>
</template>
<script setup>
const props = defineProps({
name: String,
age: Number
})
console.log(props.name) // 訪問父組件傳遞的 name
console.log(props.age) // 訪問父組件傳遞的 age
</script>
- 範例二:泛型形式 (Typescript)
<template>
<div>
<p>姓名:{{ name }}</p>
<p>年齡:{{ age }}</p>
</div>
</template>
<script setup lang="ts">
import { defineProps } from 'vue'
interface Props {
name: string
age: number
}
const props = defineProps<Props>()
console.log(props.name) // 訪問父組件傳遞的 name
console.log(props.age) // 訪問父組件傳遞的 age
</script>
defineEmits
作用: 用於在子組件中觸發自定義事件,父組件可以監聽這些事件並執行相應的操作。
使用方式: 在 <script setup> 語法糖中,直接使用 defineEmits() 函數。
參數: 可以是一個陣列,也可以是一個物件。
- 範例一:陣列形式
<template>
<button @click="handleClick">點擊觸發事件</button>
</template>
<script setup>
const emit = defineEmits(['my-event'])
const handleClick = () => {
emit('my-event', 'Hello from child!') // 觸發 my-event 事件,並傳遞參數
}
</script>
- 範例二:物件形式
<template>
<button @click="handleClick">點擊觸發事件</button>
</template>
<script setup>
const emit = defineEmits({
'my-event': (data: string) => {
return true // 返回 true 表示驗證通過
}
})
const handleClick = () => {
emit('my-event', 'Hello from child!') // 觸發 my-event 事件,並傳遞參數
}
</script>
- 父組件如何使用
<template>
<MyComponent
name="John"
age="30"
@my-event="handleMyEvent"
/>
</template>
<script setup>
import MyComponent from './MyComponent.vue'
const handleMyEvent = (data) => {
console.log('Received from child:', data)
}
</script>
- 總結
defineProps 和 defineEmits 是 Vue 3 中非常重要的兩個 API,它們使得父子組件之間的溝通變得更加清晰和簡單。透過 defineProps,父組件可以將數據傳遞給子組件;透過 defineEmits,子組件可以將事件傳遞給父組件。
- 父組件要添加的部分
<template>
<div>
<ChildComponent
v-model:searchQuery="searchQuery"
v-model:activeIndex="activeIndex"
v-model:activeIndex2="activeIndex2"
/>
<p>搜索关键字: {{ searchQuery }}</p>
<p>激活索引1: {{ activeIndex }}</p>
<p>激活索引2: {{ activeIndex2 }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const searchQuery = ref('');
const activeIndex = ref(0);
const activeIndex2 = ref(0);
</script>
- 子組件要添加的部分
// 雙向綁定的設定
const emit = defineEmits([
'update:searchQuery',
'update:activeIndex',
'update:activeIndex2'
]);
const updateSearchQuery = (event) => {
emit('update:searchQuery', event.target.value); // 更新父组件中的 searchQuery
};
const updateActiveIndex = (index) => {
emit('update:activeIndex', index); // 更新父组件中的 activeIndex
};
const updateActiveIndex2 = (index) => {
emit('update:activeIndex2', index); // 更新父组件中的 activeIndex2
};