likes
comments
collection
share

vue3 setup script+Typescript实战用法(二)——ref、defineProps、defineEmits

作者站长头像
站长
· 阅读数 15

ref

定义一个子组件,想要通过ref拿到子组件的方法或者实例时,ts编译不通过,此时可以这样做

子组件:

//son.vue

<template>
    <h1>son</h1>
</template>

<script lang="ts" setup>
const count = 0

const fn = () => {
    console.log('-----------子组件的方法-----------')
}

defineExpose({ fn, count })
</script>

父组件:

//father.vue

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

<script lang="ts" setup>
import { ref } from 'vue'
import Son from './son.vue'

interface sonData {
    fn: () => void
    count: number
}

const sonRef = ref<InstanceType<typeof Son> & sonData>()

const a = onMounted(() => {
    console.log(sonRef.value?.$el)
    console.log(sonRef.value?.fn)
})

</script>

InstanceType<typeof Son>只有组件默认的方法,没有私有方法和数据,所以要对这个数据类型做一个扩展,自定义子组件的方法数据类型,再合并,这样就可以拿到子组件的实例和方法。

如果只想拿到子组件的数据的方法,其它的公有方法不需要,那可以把InstanceType<typeof Son>删掉,直接传入一个子组件方法的数据类型即可。

defineProps

vue3 setup中提供了defineProps的函数,普通写法的话,是没有类型提示的,也就是说写错了也不会报错。

我提供了两种写法,一种是泛型的写法,另一种是定义值的写法。

(推荐写法)
interface Form {
    age: number
    name:string
}

const props = defineProps<{
    msg: string
    form?: Form
}>()
import { PropType } from 'vue'

const props = defineProps({
    msg: {
        type: String,
        required: true,
    },
    form: {
        type: Object as PropType<Form>,
        required: false,
        default() {
            return {
                age: 99999,
            }
        },
    },
})

这两种都能得到很好的代码提示,第一种会比较简洁一点,但是只是使用defineProps是没有办法用默认值的,如果想要默认值,可以加上withDefaults这个API。推荐使用第一种写法。

interface Form {
    age: number
    name:string
}

const props = withDefaults(defineProps<{
    msg: string
    form?: Form
}>(),{
    form: {
        age: 1,
        name: "vue",
    }
  }
)

defineEmits

defineEmits也是同样的道理,不能得到很好的事件提示。

const emits = defineEmits<{
    (e: 'emits', data: number): void
    (e: 'ws', data: string): void
}>()

const emit = () => {
    emits('ws', '27')
}

这样就能得到很好的代码提示 vue3 setup script+Typescript实战用法(二)——ref、defineProps、defineEmits