Vue3:Typescript与组合式API、defineProps、defineEmits等使用

标注类型:props

使用 defineProps()

使用 <script setup>

在使用 <script setup> 时,defineProps() 宏函数支持从它的参数中推导类型:

  • 运行时声明
<script setup lang="ts">
/**
 *  type:参数类型
 *  required:必须传参(默认:false)
 *  default:默认值
 * /
const props = defineProps({
  name: {
    type: String,
    required: true
  },
  title: {
    type: Number,
       required: false
  },
  status: Boolean
})
</script>
  • 基于类型的声明
<script setup lang="ts">
/**
 * 方式一:通过泛型参数
 */
const props = defineProps<{
  name?: string,
  title: number,
  status?: boolean
}>()

/**
 * 方式二:编写单独接口
 */
interface Props {
  name?: string,
  title: number,
  status?: boolean
}
const props = defineProps<Props>()

// ?代表可选参数 可以不用传
</script>

注意:接口或对象字面类型可以包含从其他文件导入的类型引用,但是,传递给 defineProps 的泛型参数本身不能是一个导入的类型, 这是因为Vue 组件是单独编译的,编译器目前不会抓取导入的文件以分析源类型(这里只是 Vue3.2 不支持,可能在之后的版本中会支持),即:

<script setup lang="ts">
// 支持
interface Props {
  /****/
}
defineProps<Props>()

// 不支持
import { Props } from './Props'
defineProps<Props>()
</script>
设置默认值

当使用基于类型的声明时,我们失去了为 props 声明默认值的能力。这可以通过 withDefaults 编译器宏解决:

<script setup lang="ts">
const props = withDefaults(defineProps<{
  name: string
  title?: string
  num: number[]
}>(), {
  title: '测试标题',
  num: () => [10, 20, 30, 40, 50]
})
</script>

标注类型:emits

使用 defineEmits()

<script setup lang="ts">
// 运行时
const emit = defineEmits(['change', 'update'])

// 基于类型
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', array: number[]): void
}>()

// 使用
emit('change', 10)
</script>

标注类型:ref()

  • 基本使用

ref 会根据初始化时的值推导其类型,也可指定具体类型:

<script setup lang="ts">
import {ref} from 'vue'
// 推导类型为 number
const count = ref(100)
// 指定具体类型
const val = ref<string>('你好世界')
</script>
  • 复杂类型使用

通过使用 Ref 这个类型来指定更为复杂的类型:

<script setup lang="ts">
import {ref} from 'vue'
import type {Ref} from 'vue'

// 标识既可以是数值类型 也可以是布尔类型
const count: Ref<number | boolean> = ref(100)
// 或者直接使用 ref() 传入一个泛型参数,来覆盖默认的推导行为
const value = ref<string | boolean>(true)
</script>

注意:如果你指定了一个泛型参数但没有给出初始值,那么最后得到的就将是一个包含 undefined 的联合类型,如:

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

// 推导类型为Ref<number | boolean | undefined>
const count = ref<number | boolean>()
console.log(count.value)// 结果:undefined
</script>

标注类型:reactive()

reactive() 也会隐式地从它的参数中推导类型:

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

// 推导得到的类型:{ name: string }
const user = reactive({name: '张三'})

// 使用接口
interface User {
  name: string
  age: string | number
  gender?: string
}

const user: User = reactive({name: '张三', age: 23})
// 或者使用 reactive 泛型
const user = reactive<User>({name: '张三', age: 23, gender: '男'})
</script>
标注类型:computed()

computed() 会自动从其计算函数的返回值上推导出类型:

<script setup lang="ts">
import {ref, computed} from 'vue'

const age = ref(23)

// 推导类型:ComputedRef<number>
const userAge = computed(() => age.value++)

// 使用泛型
const userAge = computed<number>(() => {
  // 若返回值不是 number 类型则会报错
  return 23;
})

// 设置 getter setter
const userAge = computed({
  get: () => {
  },
  set: () => {
  }
})
</script>
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_何同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值