一:默认情况下在<script setup>
语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过definExpose()
编译宏指定那些属性和方法允许访问。
需要注意的两点情况是
- 仅在vue 3.3+ 中支持
- definExpose编译宏的作用是显示暴露组件内部的属性和方法
- 子组件可以通过ref获取父组件的DOM,通过调用子组件暴露的属性和方法实现组件通信
二:这里我用definExpose写了一个关于弹框的demo,基于vue+Element Plus完成了组件通信,通过这种方式使得vue3的组件编写更加直观和简单。
- 在父组件ArticalChannel.vue中
<template>
<div class="main-box">
<el-card style="width:1000px;height:780px;">
<template #header>
<div class="card-header">
<span>文章分类</span>
<el-button @click="AddSort">添加分类</el-button>
</div>
</template>
<el-table :data="tableData" border style="width: 100%">
<el-table-column type="index" label="序号" width="180" />
<el-table-column prop="classificationName" label="分类名称" />
<el-table-column prop="classAlias" label="分类别名" />
<el-table-column align="right">
<template #default="scope">
<el-button size="small" @click="handleEdit(scope.row)">
编辑
</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<add-dialog ref="childRef"></add-dialog>
</div>
</template>
<script setup>
import { ref } from 'vue'
import addDialog from './componts/add.vue'
const tableData = [
{
id:'1',
classificationName: '记者',
classAlias: 'journalist',
},
{
id:'2',
classificationName: '主持人',
classAlias: 'emcee',
},
]
const childRef = ref();
const handleEdit = (row)=>{
childRef.value.open(row)
}
const AddSort = ()=>{
childRef.value.open({})
}
</script>
<style scoped>
.main-box{
margin-left: 50px;
}
.card-header{
display: flex;
align-items: center;
justify-content: space-between;
}
</style>
父组件中使用ref="childRef"
访问子组件实例并调用暴露的属性和方法,下面子组件使用defineExpose暴露子组件内部的open
方法。点击添加分类和编辑分类,实现弹框的一个简易封装。
- 在子组件add.vue中
<template>
<el-dialog
v-model="dialogVisible"
:title="form.id?'编辑分类':'添加分类'"
width="500"
>
<el-form :model="form" :rules="rules" ref="formRef">
<el-form-item prop="classificationName" label="分类名称:">
<el-input v-model="form.classificationName"></el-input>
</el-form-item>
<el-form-item prop="classAlias" label="分类别名:">
<el-input v-model="form.classAlias"></el-input>
</el-form-item>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确认 </el-button>
</div>
</el-form>
</el-dialog>
</template>
<script setup>
import { ref } from 'vue'
const dialogVisible = ref(false)
const form = ref({
classificationName: '',
classAlias: '',
})
const rules = {
classificationName: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],
classAlias: [
{ required: true, message: '请输入分类别名', trigger: 'blur' },
],
}
//组件向外暴露一个open方法
//1:表单无渲染 添加
//2:表单需要渲染 编辑
//3:open打开弹窗
const open = (row)=>{
dialogVisible.value = true
form.value = {...row} //添加重置了表单内容 编辑存储了回显数据
}
defineExpose({
open
})
const formRef = ref(null)
const submitForm = ()=>{
formRef.value.validate( async (valid) => {
if (valid) {
//确认添加 确认修改
console.log('submit!')
} else {
return false
}
})
}
</script>
三:效果展示如下
vue3中defineExpose的使用展示