defineExpose 、defineProps、defineEmits 是vue3的写法并且是一个仅 <script setup>
中可用的编译宏命令,并不需要显式地导入;
defineExpose 来显式指定在 <script setup>
组件中要暴露出去的属性。
defineProps、defineEmits在vue3的非语法糖setup和在vue2中的写法是 props,emit
defineExpose 子传父
(用在子组件,暴露想传递的值或方法,父组件通过ref属性获取子组件暴露的)
1. 作用
defineExpose
定义:用于组件通信中父级组件调用操作子组建方法和响应式属性参数能力,即子组件将值和方法传给父组件。
2. 原理
使用 <script setup>
的组件是默认关闭的——即通过模板引用或者 $parent
链获取到的组件的公开实例,不会暴露任何在 <script setup>
中声明的绑定。
那么,通过 defineExpose
编译器宏来显式指定在 <script setup>
组件中要暴露出去的属性
然后,父组件通过ref属性访问子组件
3. 实例
父组件:
<Index ref="childeRef"></Index>
<script setup>
import Index from "./index.vue";
const childeRef = ref();
function test() {
console.log(childeRef.value.msg) // Hello World
}
onMounted(() => {
let flag:boolean = true;
let value:number= 5;
childeRef.value.childFn(flag,value) // 调用子组件函数, 输出 6
})
</script>
子组件:
<script setup>
import {ref} from "vue";
function childFn(type:boolean, data:number) {
console.log('我是子组件');
if(data){
let value = data + 1;
return value;
}
}
const msg = 'Hello World';
const num = ref(0);
defineExpose({ //暴露想要传递的值或方法
msg,
childFn,
});
</script>
defineProps 父传子
(用在子组件,接收父组件的传值,用来声明props)
1. 作用
它可以帮助我们在组件中自定义 props,并定义它们的数据类型和默认值。使用这个新特性,可以更加方便地管理组件的 Props 数据
2. 原理
defineProps() 宏中的参数不可以访问 <script setup>
中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中,即必须在<script setup>的顶层使用,不可以在<script setup>的局部变量中引用;
3. 实例
父组件:
<templte>
<sub-task-detail
v-model:open="subTaskDetailVisible"
:task-info="task"
:sub-task-id="subTaskId"
:tab="tabIndex"
/>
</templte>
<script setup>
const subTaskDetailVisible = ref(false)
const handleDetail = (row) => {
subTaskDetailVisible.value = true
subTaskId.value = row.id
tabIndex.value = 1
}
</script>
子组件:
<script setup>
import { ref, watch, onMounted, onBeforeUnmount, h } from 'vue'
import { subTaskDetail, downloadLog } from '@/api/detail'
import BigDataList from './BigDataList.vue'
import dayjs from 'dayjs'
import { useI18n } from 'vue-i18n'
import { MIGRATION_MODE, SUB_TASK_STATUS } from '@/utils/constants'
const { t } = useI18n()
const props = defineProps({
open: Boolean,
taskInfo: Object,
subTaskId: [String, Number],
tab: [String, Number]
})
//也可以let props = defineProps(['open','taskInfo','subTaskId','tab']);
onMounted(() => {
visible.value = props.open
})
</script>
defineEmits 子传父
(用在子组件,将子组件的方法传递给父组件,用来声明emits)
1. 作用
用于在setup
中注册自定义事件,方便开发者监听和绑定事件。是一个宏函数,使用时无需导入
2. 原理
不可以访问 <script setup>
中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中,即defineEmits必须放在全局,否则报错。
3. 实例
父组件:
<template>
<add-jdbc ref="addJdbcRef" @finish="finishAddJdbc" />
</template>
<script setup>
import { reactive, ref, computed, watch, onMounted, toRaw, h, compile } from 'vue'
import AddJdbc from '../components/AddJdbc.vue'
import { sourceClusters, targetClusters, sourceClusterDbsData, targetClusterDbsData } from '@/api/task'
const finishAddJdbc = (type) => {
if (type === 'ORACLE'||type === 'MYSQL') {
getSourceClustersData()
} else {
getTargetClustersData()
}
}
</script>
子组件:
<script setup>
//defineEmits接受一个数组,元素为自定义事件名
//返回一个触发器,用于触发事件,第一个参数是具体事件名,第二个是传递的值
emits = defineEmits([`finish`])
const submit = () => {
// save
data.loading = true
const param = {
clusterName: data.form.name,
dbType: data.form.dbType,
deployType: data.form.nodes.length > 1 ? 'CLUSTER' : 'SINGLE_NODE',
nodes: []
}
addJdbc(param).then((res) => {
data.loading = false
if (Number(res.code) === 200) {
Message.success({ content: `Create success` })
emits(`finish`, data.form.dbType)
}
close()
})
}