开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情
一、问题
在Vue3中,父组件可通过创建一个ref(null),然后将赋值的元素写在当前子组件上即可,在需要的时候,通过定义的响应式变量即可获取,获取后即可取得当前子组件内部dom以及当前子组件内部变量方法等,并且直接使用子组件内部方法。但是有时候获取的时候返回的没有什么信息只有一个{_v_skin:true}这个信息,这条信息表示数据无法响应。
二、原因及方法
原因: 使用 <script setup>
语法糖的组件是默认关闭的,也即通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup>
中声明的绑定。
方法: 为了在 <script setup>
语法糖组件中明确要暴露出去的属性,使用 defineExpose 编译器宏将需要暴露出去的变量与方法放入暴露出去就可以.
三、[Vue3] defineExpose要在方法声明定义以后使用
Vue3中的setup默认是封闭的,如果要从子组件向父组件暴露属性和方法,需要用到defineExpose。 和defineProps、defineEmits一样,这三个函数都是内置的,不需要import,不过defineProps,defineEmits都会返回一个实例,而defineExpose是没有返回值的。
const props = defineProps({})
const emit = defineEmits([])
defineExpose({})
四、defineExpose的使用
子组件Child.vue
<template>
{{ name }}
</template>
<script setup>
import { ref } from 'vue'
const name = ref("张三")
const sayName = ()=>{
console.log("我叫 "+name.value)
}
defineExpose({
name,
sayName
});
</script>
父组件Father.vue
<template>
<Child ref="child"></Child>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const child = ref(null)
onMounted(()=>{
console.log(child.value.name) // "张三"
child.value.sayName() // "我叫张三"
})
</script>
结束语
1、向外暴露的时候变量会自动解包,比如上面子组件的name:ref<String>
暴露到父组件的时候自动变成了name:String
.
2、注:defineExpose一定要在变量和方法声明定义之后再使用。
不知道以后会不会有修改,不过在2023/02/22
,如果defineExpose
写在变量和函数前面,那么浏览器的控制台会输出很多警告,并且最终将该页面卡死。