如何在 Vue3 中使用 TypeScript 定义 ref 的类型(绑定到模板)?

问题描述 投票:0回答:8

模板:

<tremplate>
  <div ref="element"></div>
</template>

脚本:

export default {
  setup() {
    const element = ref(null);
    return {
      element,
    };
  },
};

这是在 vue3 中定义 ref 的正常方法,但是是以 JavaScript 的方式。 如果我使用 TypeScript,我需要为值定义一个类型

element
,对吗?

如何确保值的类型正确

element

typescript vue.js vuejs3
8个回答
54
投票
<template>
   <ChildComponent ref="childRef">
</template>
<script lang="ts" setup>
import ChildComponent from './ChildComponent.vue'
import { ref } from 'vue'

const childRef = ref<InstanceType<typeof ChildComponent>>()
childRef.value.childMethods()

</script>


41
投票

嗯,这取决于您是否需要键入并提供成员信息(公共属性、方法等)。如果你这样做,那么你需要为它定义一个类型;否则,您不必这样做,只需使用

.value
访问未包装的引用,即可将其保留为
any
类型(我打赌您已经找到了这个)。

但是如果必须这样做,您需要告诉编译器它是什么或者它将被分配给什么。为此,您需要使用 ref

 的第三个重载(不带参数)并显式将泛型类型设置为所需类型 - 在您的情况下,您需要 HTMLDivElement
 (或简单地 
HTMLElement
如果您不关心它必须提供的特定成员)。

export default defineComponent({ setup() { const el = ref<HTMLDivElement>(); onMounted(() => { el.value // DIV element }); return { el } } })
在 JavaScript 中,没有类型检查,因此在 

null

 函数上传递 
ref
 与不传递任何内容一样好(这对于模板引用来说尤其没问题)*;从某种意义上说,它甚至可能会被认为具有误导性,因为展开的值实际上解析为其他东西
但是null

* 使用 Composition API 时,“反应式引用”和“模板引用”的概念是统一的。我们在已安装的钩子上访问这种特定类型的

ref

 的原因是因为 DOM 元素将在初始渲染后
分配给它。 参考资料:

    https://v3.vuejs.org/guide/composition-api-template-refs.html#template-refs

14
投票

const el = ref<HTMLDivElement>();

el

不是 HTMLDivElement。相反,它是元素的代理。该代理的

$el
是实际的 HTMLDivElement。虽然我不确定我是否做对了。在组件中,我设法将其键入如下:
import { ComponentPublicInstance, defineComponent, ref } from 'vue';

export default defineComponent({
  // snipped...
  setup() {
    const field = ref<ComponentPublicInstance<HTMLInputElement>>();
    return {
      field,
      fun() { field.value.$el.value = 'some value'; }
    };
  }
  // snipped...
});



7
投票
Vue 3 组合 API

<template> <input ref="fileInput" style="display: none;" type="file" @change="onFileSelected" /> <button @click="fileInput?.click()">Pick Files</button> </template> <script setup lang="ts"> import { ref } from 'vue' const fileInput = ref<HTMLDivElement | null>(null) function onFileSelected(event: any) { console.log("Event: " + event) } </script>

第二个例子

<template> <div ref="coolDiv">Some text</div> <button @click="changeCoolDiv">Pick Files</button> </template> <script setup lang="ts"> import { ref } from 'vue' const coolDiv = ref<HTMLDivElement>() function changeCoolDiv() { if(coolDiv) { coolDiv.value // Div element } } </script>



4
投票
您可以使用VNodeRef。

const swiperRef = ref<VNodeRef>();



4
投票
来自 Vue 3 文档:

使用

<script setup>

的组件默认是关闭的 - 即,通过模板引用或

$parent
链检索的组件的公共实例,不会公开 内部声明的任何绑定。
要显式公开组件中的属性,请使用 

defineExpose

编译器宏: <script setup> import { ref } from 'vue' const a = 1 const b = ref(2) defineExpose({ a, b }) </script>

当父级通过模板引用获取此组件的实例时,检索到的实例将具有
{ a: number, b: number }

的形状(引用会像普通实例一样自动展开)。

示例代码

来自文档 组件

MyModal.vue

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

const isContentShown = ref(false)
const open = () => (isContentShown.value = true)

defineExpose({
  open
})
</script>

父组件
App.vue

:

<script setup lang="ts">
import MyModal from './MyModal.vue'

const modal = ref<InstanceType<typeof MyModal> | null>(null)

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



1
投票
vue-class-component

软件包(这里是 beta v8,但与

@Component
相同,而不是
@Option
将在早期版本中工作):
<template>
  <div ref="element">
    <MyOtherComponent ref="otherComponent" />
  </div>
</template>

<script lang="ts">
import { Options, Vue } from 'vue-class-component'
import MyOtherComponent from '../MyOtherComponent.vue'

@Options({
  components: {
    MyOtherComponent,
  },
})

export default class MyComponent extends Vue {
  $refs!: {
    element: HTMLDivElement,
    otherComponent: InstanceType<typeof MyOtherComponent>,
  }

  mounted() {
    this.$refs.otherComponent.myOtherComponentMethod()
  }
}
</script>



0
投票
输入 ref()

,在 Ref

 中使用类型 
vue
示例:

import type { Ref } from 'vue' name: Ref<string> = ref() interface IUser { name: string, sex: string } user: Ref<IUser> = ref({ name: '', sex: '' })

© www.soinside.com 2019 - 2024. All rights reserved.