需求
在父组件内调用子组件内的事件从而改变子组件的某些状态,父子组件使用<script setup>
语法糖,父组件通过给子组件定义ref访问其内部事件。这看起来完全没毛病,理想很丰满,现实很骨感,写完就是访问不到,还报错,离离原上谱,这究竟是为啥
经过一番调查,我才明白setup语法糖需要用defineExpose把要读取的属性和方法单独暴露出去
,这就不得不反思一下自己当初是怎么学习的使用setup语法糖,回想好像只是在查阅资料时看到有人贴了一段代码是这样方式就直接照猫画虎的直接使用,根本没有去查阅官方文档去细致全面的学习,呼伦吞枣是真的会挖很多坑等待自己探索
下面我做了一个测试,我创建两个子组件,一个使用setup语法糖,另一个使用setup()函数,都在父组件通过ref去访问,打印看结果
父组件:HomeView.vue
<template>
<div class="home">
<myChild ref="child" />
<myChild2 ref="child2" />
<button @click="add">点击</button>
</div>
</template>
<script setup>
import myChild from './myChild.vue'
import myChild2 from './myChild2.vue'
import { ref } from 'vue'
const child = ref(null)
const child2 = ref(null)
const add = () => {
console.log('child=>', child.value, '========', 'child2=>', child2.value)
// child.value.insert()
// child2.value.insert()
}
</script>
子组件1:myChild.vue
<template>
<div class="about">
<h1 @click="insert">myChild:{{ num }}</h1>
</div>
</template>
<script setup>
import { ref } from 'vue'
const num = ref(0)
const insert = () => {
num.value++
}
</script>
子组件2:myChild2.vue
<template>
<div class="about">
<h1 @click="insert">myChild2:{{ num }}</h1>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup () {
const num = ref(0)
const insert = () => {
num.value++
}
return {
num,
insert
}
}
}
</script>
结果
从下图结果可以看出,可以通过ref访问myChild2组件,但是无法访问myChild组件,
原因
vue3项目使用<script setup>
语法糖相比于使用setup()
函数会更加方便简洁,但前者会将组件私有化
,也就是说使用<script setup>的组件中的数据和事件无法被外部访问
,此时父组件就无法通过ref去访问该子组件。
除非主动对外暴露 setup 中的数据和方法,使用 defineExpose
API,此时你可以向外暴露任何你允许外部访问的
<!-- myChild -->
<script setup>
import { ref, defineExpose } from 'vue'
const num = ref(0)
const insert = () => {
num.value++
}
// 向外暴露 insert 事件
defineExpose({ insert, a: 1, b: 2 })
</script>