Vue3组件通信之二_defineExpose编译器宏函数
文章目录
- Vue3组件通信之二_defineExpose编译器宏函数
- 1. defineExpose
- 2.简单理解
- 3. 实战案例
- 1. 父子组件之间通信
- 1. 子组件中通过defineExpose暴露属性或方法
- 2. 父组件中使用子组件暴露的方法
- 2. 同级(兄弟)组件之间方法调用或传值
- 1. 子组件1
- 2. 子组件2
- 2. 借助父组件实现子组件1与子组件2之间通信
1. defineExpose
官网文档:https://cn.vuejs.org/api/sfc-script-setup.html#defineexpose
使用
<script setup>
的组件是默认关闭的——即通过模板引用或者$parent
链获取到的组件的公开实例,不会暴露任何在<script setup>
中声明的绑定。可以通过
defineExpose
编译器宏来显式指定在<script setup>
组件中要暴露出去的属性:
<script setup>
import { ref } from 'vue'const a = 1
const b = ref(2)defineExpose({a,b
})
</script>
当父组件通过模板引用的方式获取到当前组件的实例,获取到的实例会像这样 { a: number, b: number }
(ref 会和在普通实例中一样被自动解包)
2.简单理解
defineExpose
使用在子组件中或兄弟组件之间的通讯- 可以暴露属性或方法给父组件使用和调用
3. 实战案例
1. 父子组件之间通信
1. 子组件中通过defineExpose暴露属性或方法
- 子组件中定义,
SysDictAddComponent.vue如下
<script setup lang="ts">
import { ref, defineExpose} from "vue";const addSubmit = () => {//...
}let msg = ref('hello,jinshengyuan')
//暴露属性和方法给其父组件使用
defineExpose({msg,addSubmit,updateFrom
})
</script>
2. 父组件中使用子组件暴露的方法
- 引入子组件时给给组件设置ref属性如
<SysDictAddComponent ref="sysDictAddComponent"></SysDictAddComponent>
- setup函数中定义ref对象,
const sysDictAddComponent = ref()
- 通过
sysDictAddComponent.value.属性
或sysDictAddComponent.value.方法名进行使用
- 具体使用如下面末尾部分
<template><a-drawertitle="新增用户":width="720":visible="visible":body-style="{ paddingBottom: '80px' }":footer-style="{ textAlign: 'right' }"@close="onClose"><!--新增用户form组件--><SysDictAddComponent ref="sysDictAddComponent"></SysDictAddComponent><!--按钮--><template #extra><a-space><a-button @click="onClose">关闭</a-button><a-button type="primary" @click="onSubmit">提交</a-button></a-space></template></a-drawer>
</template>
<script setup lang="ts">
import {ref, watch} from 'vue';
import SysDictAddComponent from "../../components/sys/SysDictAddComponent.vue";//接收父组件传递的对象
const props = defineProps<{subVisible: boolean
}>()
//抽屉是否显示函数
const visible = ref<boolean>(false);//监听子组件传递的subVisible值并给visible重新赋值
watch(() => (props.subVisible), (newVal, oldVal) => {console.log("new:" + newVal, "old:" + oldVal)visible.value = newVal
})//定义emit事件
const emit = defineEmits(['changeSubVisible','addSuccess'])const onClose = () => {visible.value = false;//通知父组件改属性emit('changeSubVisible', false)
};
//获取子组件暴露的对象
const sysDictAddComponent = ref()
//提交时校验
const onSubmit = () => {//visible.value = false;//调用SysUserAddComponent组件中通过defineExpose暴漏的addSubmit方法sysDictAddComponent.value.addSubmit()//
}
</script>
2. 同级(兄弟)组件之间方法调用或传值
注意:同级(兄弟)组件之间传值是借助父组件来完成的,
1. 子组件1
子组件1
FormButton.vue
<template><el-button type="primary" @click="submit">提交</el-button><el-button @click="reset">重置</el-button><el-button @click="close">关闭</el-button>
</template>
<script setup lang="ts">
import {defineEmits, inject, ref} from 'vue'//调用父组件的方法,执行关闭操作
const emits = defineEmits(['doSubmit','doClose']);
const close = () => {emits('doClose')
}const submit = () => {emits('doSubmit')
} //1.使用inject函数调用隔代组件中provide提供的函数
/*const doSubmitHandler = inject('doSubmit',()=>{},false)
const doRectHandler = inject('doReset',()=>{},false)
const submit = () => {//doSubmitHandler.call(null)//console.log(roleFormComponent.value.roleFormRef)
}
const reset = () => {//doRectHandler.call(null)//roleFormComponent.value.resetForm()
}*//*
2. 使用defineEmits函数调用父组件的方法
const emits = defineEmits(['doSubmit', 'doReset', 'doClose']);
const submit = () => {emits('doSubmit')
}
const reset = () => {emits('doReset')
}
const close = () => {emits('doClose')
}
2. 父组件中使用如下:
<FormButton @doSubmit="test" @doReset="rest" @doClose="close"></FormButton>
父组件中的三个方法如下:
const test = ()=>{console.log("我是父组件提交方法1")
}const rest = ()=>{console.log("我是父组件重置方法2")
}const close = ()=>{console.log("我是父组件关闭方法3")
}*/</script><style scoped lang="scss"></style>
2. 子组件2
子组件2
RoleFormComponent.vue
<template><el-formref="roleFormRef":model="ruleForm":rules="rules"label-width="120px"class="demo-ruleForm":size="formSize"status-icon><el-form-item label="角色编码" prop="roleCode"><el-input v-model="ruleForm.roleCode"/></el-form-item><el-form-item><el-button type="primary" @click="submitForm(roleFormRef)">Create</el-button><el-button @click="resetForm(roleFormRef)">Reset</el-button></el-form-item></el-form>
</template><script setup lang="ts">
import {reactive, ref, defineExpose} from 'vue'
import type {FormInstance, FormRules} from 'element-plus'const formSize = ref<string>('default')
const roleFormRef = ref<FormInstance>()const submitForm = async (formEl: FormInstance | undefined) => {console.log('表单提交执行了。。。。')if (!formEl) returnawait formEl.validate((valid, fields) => {if (valid) {console.log('submit!', {...ruleForm})} else {console.log('error submit!', fields)}})
}
//暴露方法给父组件使用,然后同级(兄弟)组件借助父组件中某个子组件的ref进行方法调用
defineExpose({roleFormRef,submitForm
})
</script><style lang="scss" scoped></style>
2. 借助父组件实现子组件1与子组件2之间通信
子组件1与子组件2总各自通过
defineExpose
暴露属性或方法给父组件然后借助父组件实现子组件1与子组件2之间通信
<template><el-drawer v-model="drawer" :direction="direction" :before-close="handleClose" size="50%"><template #header><h4>{{ formTitle }}</h4></template><template #default><!--子组件1: RoleFormComponent--><RoleFormComponent ref="roleFormComponent"></RoleFormComponent></template><template #footer><div style="flex: auto;align-content: center;align-items: center"><!--子组件2:FormButton--><FormButton @doSubmit="formButtSubmit" @doClose="handleClose"></FormButton></div></template></el-drawer>
</template><script setup lang="ts">
import {ref, defineProps, watch, provide} from 'vue'
import {ElMessageBox} from 'element-plus'
import RoleFormComponent from '@/components/sys/drawer/RoleFormComponent.vue'
import FormButton from "@/components/public/FormButton.vue"
//定义props,父组件向子组件传值
const props = defineProps<{showDrawer: boolean
}>();
//显示抽屉,默认false
const drawer = ref<boolean>(false)
const formTitle = ref<string>('角色新增')watch(() => (props.showDrawer), (newVal, oldVal) => {console.log(newVal, oldVal)drawer.value = newVal
})//定义emit事件,调用父组件的方法
const emit = defineEmits(['updateDrawerVisible'])//借助父组件进行同级组件传值及方法调用,如:FormButton组件调用RoleFormComponent组件中的formButtSubmit方法
const roleFormComponent = ref()
const formButtSubmit = ()=>{console.log(roleFormComponent.value.roleFormRef)//获取RoleFormComponent组件暴露的roleFormRef及调用submitForm方法roleFormComponent.value.submitForm(roleFormComponent.value.roleFormRef)
}</script><style lang="scss" scoped></style>