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

mhd8tkvw  于 2022-12-14  发布在  Vue.js
关注(0)|答案(5)|浏览(1129)

模板:

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

脚本:

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

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

o4hqfura

o4hqfura1#

好吧,这取决于你是否需要它的类型和提供成员信息(公共属性,方法等)。否则,您不必这样做,只需使用.value访问未 Package 的引用,使其保持any类型(我敢打赌您已经猜到了这一点)。
但是如果必须这样做,你需要告诉编译器它是什么或者它将被赋值到什么上。为此,你需要使用ref的第三个重载(没有参数),并显式地将泛型类型设置为所需的类型-在你的例子中,你需要HTMLDivElement(或者如果你不关心它必须提供的特定成员,你只需HTMLElement)。

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

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

    return {
      el
    }
  }
})

在JavaScript中,没有类型检查,所以在ref函数上传递null就像不传递任何东西一样好(这对于模板引用来说尤其好)*;在某种意义上,它甚至可能会让人误解,因为展开的值实际上会解析为 * null以外的其他值。

  • 当使用Composition API时,“React式引用”和“模板引用”的概念是统一的。我们在挂载的钩子上访问这种特定类型的ref的原因是因为DOM元素将在初始渲染后被分配给它。

参考文献:

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

kd3sttzy2#

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

sh7euo9m3#

该行不正确:

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...
});
g6ll5ycj

g6ll5ycj4#

Vue 3.2以上版本

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

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

rbpvctlc5#

如果使用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>

相关问题