vue3中调用子组件的方法

1,076 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

需求简介

使用vue开发的过程中,父子组件之间除了通信之外,偶尔还需要相互调用彼此的方法。比如有时需要通知子组件更新数据或者执行某种操作,就需要调用子组件的方法。

vue2

在vue2中比较简单,假设我们有以下的子组件:

<template>
    <div> son </div>
</template>

<script>
    export default {
        name: 'son'methods: {
            say {
                console.log('I am son')
            }
        }
    }
</script>

再创建使用了子组件的父组件:

<template>
   <Son ref="son" />
</template>

<script>
    import Son from './son.vue'
    
    export deafult {
        name: 'father',
        components: { Son }
        mounted () {
            this.$ref.son && this.$ref.son.say()
        }
    }
</script>

运行后可以看到浏览器控制台打印出

微信截图_20220529144859.png 证明调用成功,但在vue3却无法这样做。

vue3

同样,先创建一个子组件:

<template>
    <div> son </div>
</template>

<script lang='ts' setup>
    function say(): void {
        console.log('I am son');
    }
</script>

然后在创建一个使用子组件的父组件:

<template>
   <Son ref="son" />
</template>

<script lang='ts' setup>
    import type { ComponentPublicInstance } from 'vue'

    import Son from './son.vue
    import { onMounted, ref } from 'vue
    
    const son = ref<ComponentPublicInstance>()
    
    onMounted((): void => {
        son.value && son.value.say()
    })
</script>

此卢浏览器控制台会报错,提示TypeError: son.value.say is not a function vue3中,如果需要调用子组件的方法,需要先在子组件中将对应的方法暴露出来, 子组件添加后代码如下:

<template>
    <div> son </div>
</template>

<script lang='ts' setup>
    import { defineExpose } from 'vue'

    function say(): void {
        console.log('I am son');
    }
    
    defineExpose({  say })
</script>

之后才可以在父组件中调用,运行后可以看到浏览器控制台打印出:

微信截图_20220529150847.png 但是在使用typeScript的情况下,编辑器会提示类型“ComponentPublicInstance”上不存在属性“say”,这是因为从vue中导出的类型ComponentPublicInstance上并没有我们加上的say声明,需要定义一个继承自ComponentPublicInstance的类型,同时扩展我们暴露出来的属性和函数:

export interface myType extends ComponentPublicInstance {
  computeNewPosition: () => {}
}

然后修改父组件中的类型:

<template>
   <Son ref="son" />
</template>

<script lang='ts' setup>
    import type { myType } from './type.ts'

    import Son from './son.vue
    import { onMounted, ref } from 'vue
    
    const son = ref<myType>()
    
    onMounted((): void => {
        son.value && son.value.say()
    })
</script>

这样编辑器就不会继续提示找不到相应的属性或者方法了。