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>