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

Sho*_*ngs 12 typescript vue.js vuejs3

模板:

<tremplate>
  <div ref="element"></div>
</template>
Run Code Online (Sandbox Code Playgroud)

脚本:

export default {
  setup() {
    const elelemt = ref(null);
    return {
      element,
    };
  },
};
Run Code Online (Sandbox Code Playgroud)

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

我该如何确保 value 的正确类型element

小智 46

<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>

Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,如果您对 ChildComponent 使用“脚本设置”,则这不起作用。您会收到此错误:`TS2344:类型'{}'不满足约束'abstract new (...args: any) =&gt; any'。` (3认同)
  • 通过额外的支持信息可以改进您的答案。请[编辑]添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以[在帮助中心](/help/how-to-answer)找到有关如何写出好的答案的更多信息。 (2认同)
  • 除此之外,您还需要添加defineExpose({ childMethods: childMethods}); 使用设置脚本时添加到 ChildComponent,以便能够从 Parent 中的引用访问该方法。 (2认同)

eid*_*ng8 13

该行不正确:

    const el = ref<HTMLDivElement>();
Run Code Online (Sandbox Code Playgroud)

不是elHTMLDivElement。相反,它是元素的代理。该$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...
});
Run Code Online (Sandbox Code Playgroud)

  • 这对于普通的 div 元素来说是错误的。对于 &lt;div ref="test"&gt;,使用: ref&lt;HTMLDivElement&gt; 对于 &lt;my-app-component ref="test"&gt;,使用 ref&lt;PublicComponentInstance&lt;MyAppComponent&gt;&gt; (7认同)

Yom*_* S. 8

嗯,这取决于您是否需要输入它并提供成员信息(公共属性、方法等)。如果你这样做,那么是的,你需要为它定义一个类型;否则,您不必这样做,并且可以简单地访问未包装的引用,.value并将其保留为类型any(我打赌您已经找到了这个)。

但是如果必须的话,你需要告诉编译器它什么或者它会被分配到什么上。为此,您需要使用(不带参数)的第三个重载ref并将泛型类型显式设置为所需的类型——在您的情况下,您想要HTMLDivElement(或者只是HTMLElement如果您不关心它的特定成员)必须提供)。

export default defineComponent({
  setup() {
    const el = ref<HTMLDivElement>();

    onMounted(() => {
      el.value // DIV element
    });

    return {
      el
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

在JavaScript中,你没有类型检查,所以传递nullref功能是一样好,不传递任何(这是模板裁判特别好)*; 从某种意义上说,它甚至可能被认为具有误导性,即未包装的值实际上解析为其他内容, null.

* 使用 Composition API 时,“reactive refs”和“template refs”的概念是统一的。我们在ref挂载钩子上访问这种特殊类型的原因是因为 DOM 元素将在初始渲染后分配给它。

参考:

  • @coyotte508 [这个](/sf/answers/4683670771/) 能回答你的问题吗? (2认同)

Mis*_*ses 6

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>
Run Code Online (Sandbox Code Playgroud)

第二个例子

<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>
Run Code Online (Sandbox Code Playgroud)