Home >Web Front-end >Vue.js >How to solve the problem of vue3 getting ref instance combined with ts InstanceType
Sometimes we have template references, but when using them, the ts prompt does not work, and there is no prompt for the component to pass The method name exposed by defineExpose, although this is not very influential, it can be solved or solved~
<!-- MyModal.vue --> <script setup lang="ts"> import { ref } from 'vue' const sayHello = () => (console.log('我会说hello')) defineExpose({ sayHello }) </script>
Then we use it at the parent level. After entering MyModalRef.value, we will find that there is no sayHello function prompt, so at this time We need to use the InstanceType tool type to get its instance type
<!-- App.vue --> <script setup lang="ts"> import MyModal from './MyModal.vue' const MyModalRef = ref() const handleOperation = () => { MyModalRef.value.sayHello } </script>
Use the InstanceType tool type to get its instance type:
<!-- MyModal.vue --> <script setup lang="ts"> import { ref } from 'vue' const sayHello = () => (console.log('我会说hello')) defineExpose({ open }) </script>
Parent use
<!-- App.vue --> <script setup lang="ts"> import MyModal from './MyModal.vue' const MyModalRef = ref<InstanceType<typeof MyModal> | null>(null) const handleOperation = () => { MyModalRef.value?.sayHello() } </script>
It seems that there is still no prompt to use InstanceType when prompted, and then input the wrong content and no error is reported before compilation..., but Vue official said this, then just listen to him (in fact, I generally don’t use it, but Also learned)
@vue official API annotates component template reference types
Vue3 and TS are definitely the most popular this year front-end technology. Many companies are using Vue3 TS Vite combination to develop new projects. The following is the rewritten sentence: Share how to use Composition-Api combined with TS types in Vue3 components.
Use
When using
<script setup lang="ts"> const props = defineProps({ foo: { type: String, required: true }, bar: Number }) props.foo // string props.bar // number / undefined </script>
This is called a runtime declaration because the parameters passed to defineProps() will be used as runtime props options.
The second way is to define the type of props through generic parameters, which is more direct:
<script setup lang="ts"> const props = defineProps<{ foo: string bar?: number }>() </script> /* or <sctipt setup lang="ts"> interface Props { foo: string bar?: number } const props = defineProps<Props>() </script> */
The compiler will try to deduce the type parameters and generate corresponding runtime options. This approach is called type-based declaration. The disadvantage of this approach is that the ability to define default values for props is lost. Using the withDefaults compiler can solve this problem
interface Props { msg?: string labels?: string[] } const props = withDefaults(defineProps<Props>(), { msg: 'hello', label: () => ['one', 'two'] })
The above code will be compiled into the equivalent default option of runtime props.
If
import { defineComponent } from 'vue' export default defineComponent({ props: { message: String }, setup(props){ props.message // 类型:string } })
Use
In
<script setup lang="ts"> // 运行时 const emit = defineEmits(['change', 'update']) //基于类型 const emit = defineEmits<{ (e: 'change', id: number): void (e: 'update', value: string): void }>() </script>
We can see that type-based declaration allows us to have more fine-grained control over the type of triggered events.
Non
If
import { defineComponent } from 'vue' export default definComponent({ emits: ['change'], setup(props, { emit }) { emit('change') //类型检查 / 自动补全 } })
Default derivation type
ref will automatically derive its type based on the value during initialization:
import { ref } from 'vue' // 推导出的类型:Ref<number> const year = ref(2022) // TS Error: Type 'string' is not assignable to type 'number'. year.value = '2022'
Specify the type through the interface
Sometimes we may want to specify a more complex type for the value in ref. You can use the Ref interface:
import { ref } from 'vue' import type { Ref } from 'vue' const year: Ref<string | number> = ref(2022) year.value = 2022 //成功
Specify the type through generics
Or, when calling ref () to override the default derivation behavior:
// 得到的类型:Ref<string | number> const year = ref<string | number>('2022') year.value = 2022 //成功
If you specify a generic parameter but do not give an initial value, the final result will be a value containing undefined Union type:
// 推导得到的类型:Ref<number | undefined> const n = ref<number>()
Default derivation type
reactive() will also implicitly derive the type from its parameters:
import { reactive } from 'vue' //推导得到的类型:{ title: string } const book = reactive({ title: 'Vue 3 指引'})
Specify the type through the interface
To explicitly specify the type of a reactive variable, we can use the interface:
import { reactive } from 'vue' interface Book { title: string year?: number } const book: Book = reactive({ title: 'Vue 3 指引' })
Default derivation Type
computed() will automatically deduce the type from the return value of its calculation function:
import { ref, computed } from 'vue' const count = ref(0) // 推导得到的类型:ComputedRef<number> const double = computed(() => count.value * 2) // TS Error: Property 'split' does not exist on type 'number' const result = double.value.split('')
Specify the type through generics
const double = component<number>(() => { // 若返回值不是 number 类型则会报错 })
When processing native DOM events, the parameters of the event processing function should be correctly marked with types, such as:
<script srtup lang="ts"> function handleChange(event) { // `event` 隐式地标注为 `any`类型 console.log(event.target.value) } </script> <template> <input type="text" @change="handleChange" /> </template>
When there is no type marking, the event parameter will automatically be recognized as any type. This will also raise a TS error if "strict": true or "noImplicitAny": true is configured in tsconfig.json. Therefore, it is recommended to explicitly annotate the types of event handler function parameters. Additionally, you may need to explicitly cast the properties on the event:
function handleChange(event: Event) { console.log((event.target as HTMLInputElement).value) }
provide and inject will usually run in different components. To correctly mark the type of injected values, Vue provides an Injectionkey interface, which is a generic type inherited from Symbol and can be used to synchronize the type of injected values between providers and consumers:
import { provide, inject } from 'vue' import type { Injectiokey } from 'vue' const key = Symbol() as Injectionkey<string> provide(key,'foo') // 若提供的是非字符串值会导致错误 const foo = inject(key) // foo 的类型: string | undefined
It is recommended to put the injected key type in a separate file so that it can be imported by multiple components.
When using a string to inject key, the type of the injected value is unknown, and the declaration needs to be displayed through generic parameters:
const foo = inject<string>('key') // 类型:string | undefined
由于提供者在运行时可能没有提供这个值,因此请注意注入的值可能仍然是未定义的。移除 undefined 类型的方法是提供一个默认值
const foo = inject<string>('foo', 'bar') // 类型:string
如果你确定该值始终被提供,则还可以强制转换该值:
const foo = inject('foo') as string
模板 ref 需要通过一个显式指定的泛型参数和一个初始值 null 来创建:
<script setup lang="ts"> import { ref, onMounted } from 'vue' const el = ref<HTMLInputElement | null>(null) onMounted(() => { el.value?.focus() }) </script> <template> <input ref="el" /> </template>
为了严格的类型安全,请使用可选链或类型守卫来访问 el.value。这是因为直到组件被挂载前,这个 ref 的值都是初始的 null,并且 v-if 将引用的元素卸载时也会被设置为 null。
有时候,我们需要为一个子组件添加一个模板引用(template reference),以便可以调用它公开的方法。举个例子,我们有一个 MyModal 子组件,其中包含一个用于打开模态框的方法:
<script setup lang="ts"> import { ref } from 'vue' const isContentShown = ref(false) const open = () => (isContentShow.value = true) defineExpose({ open }) </script>
为了获取 MyModal 的类型,我们首先需要通过 typeof 得到其类型,再使用 TypeScript 内置的 InstanceType 工具类型来获取其实例类型:
<script> import MyModal from './MyModal.vue' const modal = ref<InstanceType<typeof MyModal > | null>(null) const openModal = () => { modal.value?.open() } </script>
The above is the detailed content of How to solve the problem of vue3 getting ref instance combined with ts InstanceType. For more information, please follow other related articles on the PHP Chinese website!