1、前言
在vue3項目開發中,我們常常會遇到父子組件相互調用的場景,下面以setup語法糖格式詳細聊聊父子組件那些事兒。
2、父組件調用子組件方法
2.1 子組件Child.vue
<template>
<div>我是子組件</div>
</template>
<script setup>
// 第一步:定義子組件的方法
const sayHello = (value) => {
console.log(value)
}
// 第二部:暴露方法
defineExpose({
sayHello
})
</script>
2.2 父組件Father.vue
<template>
<button @click="getChild">觸發子組件方法</button>
<child ref="childRef" />
</template>
<script setup>
import Child from './components/child.vue'
// 定義與 ref 同名變量
const childRef = ref(null)
const getChild = () => {
// 調用子組件的方法或者變量,通過value
childRef.value.hello("hello world!");//這個方法沒測試,應該是sayHello()?
}
</script>
3、子組件調用父組件方法
3.1 父組件Father.vue
<template>
<child @sayHello="handle" />
</template>
<script setup>
import Child from './components/child.vue';
const handle = () => {
console.log('子組件調用了父組件的方法')
}
</script>
3.2 子組件Child.vue
<template>
<view>我是子組件</view>
<button @click="sayHello">調用父組件的方法</button>
</template>
<script setup>
const emit = defineEmits(["sayHello"])
const sayHello = () => {
emit('Hello World')
}
</script>
vue3 defineEmits的使用
簡介:用於父子組件通信時,子組件向父組件傳遞數據,不需要被導入即可使用,會在編譯 <script setup>
語法塊時一同編譯。注意的是 defineEmits 只能在 <script setup>
的頂層使用
使用
1、定義子組件
// 子組件 child.vue
<template>
<button @click="handelClick">傳遞給父級</button>
<button @click="add">加</button>
<button @click="decrease">減</button>
</template>
<script setup lang="ts">
const emits = defineEmits(['clickFn', 'add', 'decrease'])// 定義一個或多個自定義事件
const handelClick = () => {
emits('clickFn', { name: '張三', age: 18,id: 1 }) // 第一個參數爲自定義事件名 第二個參數爲要傳遞的數據
//上面這麼寫,傳入的參數是一個map對象,接收的時候使用.name,.age,.id
//也可以這麼做,不使用對象來傳遞參數,而是直接傳遞多個參數,這樣接收的時候,按照順序接收參數
//父組件的函數不使用對象接收,而是使用(name,age,id)來接收參數
emits('clickFn', '張三', 18,1);
}
const add = () => {
emits('add', 10) // 第一個參數爲自定義事件名 第二個參數爲要傳遞的數據
}
const decrease = () => {
emits('decrease', 3) // 第一個參數爲自定義事件名 第二個參數爲要傳遞的數據
}
</script>
2、定義父組件
// 父組件 parent.vue
<template>
<child @clickFn="updateInfo" />
<button @click="handelClick">傳遞給父級</button>
<button @click="handelAdd">加</button>
<button @click="handelDecrease">減</button>
</template>
<script setup lang="ts">
import child from './child.vue'
import { ref } from 'vue'
const num = ref(10)
const updateInfo = (userInfo) => {
console.log(userInfo) // { name: '張三', age: 18,id: 1 }
}
const handelAdd = (n) => {
num.value += n
}
const handelDecrease = (n) => {
num.value -= n
}
</script>
還可以使用defineProps來暴露給父節點使用,例如:
const props = defineProps(["onSuccess"]);
場景: 父頁面點擊按鈕,彈出對話框,對話框裏面查詢出來多條記錄,選擇其中一條記錄給父頁面的一個函數使用 , 項目實例:
父頁面
<template>
<div>
<create-form-register
ref="saveFormForRegister"
@mySuccessFun="(val: any, text: any, areaUid: any)=>setProjectRegisterFun(val, text, areaUid)"
:onSuccess="(val: any, text: any, areaUid: any) => setProjectRegisterFun(val, text, areaUid)"
/>
<div>
</template>
<script lang="ts" setup>
...
import CreateFormRegister from "./components/queryRegisterDilog.vue";//子對話框組件
//對話框子頁面需要調用的函數
const setProjectRegisterFun = (val: any, text: any, areaUid: any) => {
console.info(val + "," + text + "," + areaUid);
}
</script>
子頁面(使用defineProps 和defineEmits 經過測試都是可以的)
<template>
...
</template>
<script lang="ts" setup>
//對話框的確定按鈕點擊事件
//添加價格信息
const handleSubmit = async (isAll: boolean) => {
let projectRegister = getCurrentRecord();
if (!projectRegister) {
ElMessage({
message: "請至少選擇一條數據",
type: "warning",
});
return false;
}
handleCancel();
//props.onSuccess(projectRegister.id, projectRegister.name, projectRegister.cprjNameEn);
mySuccessFun(projectRegister);
};
const emit = defineEmits(["mySuccessFun"]);
const mySuccessFun = (projectRegister: any) => {
// emit("mySuccessFun", {
// val: projectRegister.id,
// text: projectRegister.name,
// areaUid: projectRegister.cprjNameEn,
// }); // 第一個參數爲自定義事件名 第二個參數爲要傳遞的數據
emit(
"mySuccessFun",
projectRegister.id,
projectRegister.name,
projectRegister.cprjNameEn
); // 第一個參數爲自定義事件名 第二個參數爲要傳遞的數據
};
const props = defineProps(["onSuccess"]);//暴露函數onSuccess給父頁面使用
defineExpose({ name: "", open });
</script>