搭配 TypeScript 使用 Vue​

9,484次阅读
没有评论

共计 3527 个字符,预计需要花费 9 分钟才能阅读完成。

IDE 支持

  1. Volar 是官方的 VSCode 扩展,提供了 Vue 单文件组件中的 TypeScript 支持,还伴随着一些其他非常棒的特性
  2. TypeScript Vue Plugin 用于支持在 TS 中 import *.vue 文件。

配置 tsconfig.json

通过 create-vue 搭建的项目包含了预先配置好的 tsconfig.json。

手动配置 tsconfig.json 时,请留意以下选项:

  • compilerOptions.isolatedModules 应当设置为 true,因为 Vite 使用 esbuild 来转译 TypeScript,并受限于单文件转译的限制。
  • 如果你在构建工具中配置了路径解析别名,例如 @/* 这个别名被默认配置在了 create-vue 项目中,你需要通过 compilerOptions.paths 选项为 TypeScript 再配置一遍。

Volar Takeover 模式

在每个项目里我们都运行了两个语言服务实例:一个来自 Volar,一个来自 VSCode 的内置服务。这在大型项目里可能会带来一些性能问题。为了优化性能,Volar 提供了一个叫做“Takeover 模式”的功能。在这个模式下,Volar 能够使用一个 TS 语言服务实例同时为 Vue 和 TS 文件提供支持

  • 在当前项目的工作空间下,用 Ctrl + Shift + P (macOS:Cmd + Shift + P) 唤起命令面板。
  • 输入 built,然后选择“Extensions:Show Built-in Extensions”。
  • 在插件搜索框内输入 typescript (不要删除 @builtin 前缀)。
  • 点击“TypeScript and JavaScript Language Features”右下角的小齿轮,然后选择“Disable (Workspace)”。
  • 重新加载工作空间。Takeover 模式将会在你打开一个 Vue 或者 TS 文件时自动启用。

defineComponent()

为了让 TypeScript 正确地推导出组件选项内的类型,我们需要通过 defineComponent() 这个全局 API 来定义组件

import { defineComponent } from 'vue'

export default defineComponent({
  
  props: {
    message: String
  },
  setup(props) {
    props.message 
  }
})

为组件的 props 标注类型

为了生成正确的运行时代码,传给 defineProps() 的泛型参数必须是以下之一:

  1. defineProps()
  2. interface Props {/* … */} defineProps()
script setup lang="ts">
const props = defineProps{
  foo: string
  bar?: number
}>()
/script>

script setup lang="ts">
interface Props {
  foo: string
  bar?: number
}

const props = definePropsProps>()
/script>

withDefaults 编译器

为 props 声明默认值的能力。这可以通过 withDefaults 编译器宏解决:

export interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(definePropsProps>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

复杂的 prop 类型

使用 PropType 工具类型:

import type { PropType } from 'vue'

const props = defineProps({
  book: Object as PropTypeBook>
})


import { defineComponent } from 'vue'
import type { PropType } from 'vue'

interface Book {
  title: string
  author: string
  year: number
}

export default defineComponent({
  props: {
    book: Object as PropTypeBook>
  }
})

组件的 emits 标注类型

script setup lang="ts">

const emit = defineEmits(['change', 'update'])


const emit = defineEmits{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
/script>

ref() 标注类型

import { ref } from 'vue'
import type { Ref } from 'vue'

const year: Refstring | number> = ref('2020')

year.value = 2020 

或者,在调用 ref() 时传入一个泛型参数


const year = refstring | number>('2020')

year.value = 2020 

reactive() 标注类型

要显式地标注一个 reactive 变量的类型,我们可以使用接口:

import { reactive } from 'vue'

interface Book {
  title: string
  year?: number
}

const book: Book = reactive({ title: 'Vue 3 指引' })

computed() 标注类型

通过泛型参数显式指定类型:

const double = computednumber>(() => {
  
})

事件处理函数标注类型

script setup lang="ts">
function handleChange(event) {
  
  console.log(event.target.value)
}
/script>

template>
  input type="text" @change="handleChange" />
/template>


function handleChange(event: Event) {
  console.log((event.target as HTMLInputElement).value)
}

为 provide / inject 标注类型

Vue 提供了一个 InjectionKey 接口,它是一个继承自 Symbol 的泛型类型,可以用来在提供者和消费者之间同步注入值的类型:

import { provide, inject } from 'vue'
import type { InjectionKey } from 'vue'

const key = Symbol() as InjectionKeystring>

provide(key, 'foo') 

const foo = inject(key) 
const foo = injectstring>('foo') 
当提供了一个默认值后,这个 undefined 类型就可以被移除:const foo = injectstring>('foo', 'bar') 
如果你确定该值将始终被提供,则还可以强制转换该值:const foo = inject('foo') as string

模板引用标注类型

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

const el = refHTMLInputElement | null>(null)

onMounted(() => {
  el.value?.focus()
})
/script>

template>
  input ref="el" />
/template>

组件模板引用标注类型

为了获取 MyModal 的类型,我们首先需要通过 typeof 得到其类型,再使用 TypeScript 内置的 InstanceType 工具类型来获取其实例类型:

!-- App.vue -->
script setup lang="ts">
import MyModal from './MyModal.vue'

const modal = refInstanceTypetypeof MyModal> | null>(null)

const openModal = () => {
  modal.value?.open()
}
/script>

如果组件的具体类型无法获得,或者你并不关心组件的具体类型,那么可以使用 ComponentPublicInstance。这只会包含所有组件都共享的属性,比如 $el。

import { ref } from 'vue'
import type { ComponentPublicInstance } from 'vue'

const child = refComponentPublicInstance | null>(null)

原文地址: 搭配 TypeScript 使用 Vue​

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-10-07发表,共计3527字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)