Vuejs typescript this.$refs.<refField>.value 不存在

IT技术 javascript typescript vue.js vuejs2 vue-component
2021-03-02 18:55:34

在用typescript重写我的 VueJs 项目时,我遇到了typescript错误。

这是具有自定义 v-model 的组件的一部分。

html 中的输入字段有一个名为“plate”的引用,我想访问它的值。该字段上的@input 调用下面编写的更新方法。

typescript抱怨盘子上不存在value。

@Prop() value: any;

update() {
    this.$emit('input',
        plate: this.$refs.plate.value
    });
}

模板:

<template>  
<div>
    <div class="form-group">
        <label for="inputPlate" class="col-sm-2 control-label">Plate</label>

        <div class="col-sm-10">
            <input type="text" class="form-control" id="inputPlate" ref="plate" :value="value.plate" @input="update">
        </div>
    </div>

</div>
</template>
6个回答

你可以这样做:

class YourComponent extends Vue {
  $refs!: {
    checkboxElement: HTMLFormElement
  }

  someMethod () {
    this.$refs.checkboxElement.checked
  }
}

从这个问题:https : //github.com/vuejs/vue-class-component/issues/94

这不起作用。也许它曾经,但不是今天(使用 vue-cli 3)。
2021-04-20 18:55:34
我正在使用let mycomp = Vue.extend({})语法。我怎么能在这方面做同样的事情?我还应该使用上述语法吗?
2021-04-24 18:55:34
嗯,谢谢......我实际上讨厌 vue 类组件中的装饰器。
2021-04-28 18:55:34
您可以创建一个表示 refs 类型的接口,然后转换为该接口。至少这样你就避免了 any,你的视图将根据它进行类型检查。
2021-04-29 18:55:34
我需要写$refs!:(注意感叹号)才能让它工作,但我正在使用vue-property-decorator. @George 如果我的修复没问题,你能编辑答案吗?不想为类组件用户破坏它,因为那里可能存在一些差异(编辑:啊,感叹号实际上在您发布的链接中)
2021-05-12 18:55:34

编辑 - 2021-03(组合 API)

更新此答案是因为 Vue 3(或组合 API 插件,如果您使用的是 Vue 2)有一些新功能。

<template>
  <div ref="root">This is a root element</div>
</template>

<script lang="ts">
  import { ref, onMounted, defineComponent } from '@vue/composition-api'

  export default defineComponent({
    setup() {
      const root = ref(null)

      onMounted(() => {
        // the DOM element will be assigned to the ref after initial render
        console.log(root.value) // <div>This is a root element</div>
      })

      return {
        root
      }
    }
  })
</script>

编辑 - 2020-04:

vue-property-decorator库提供了我推荐的@Ref而不是我的原始答案。

import { Vue, Component, Ref } from 'vue-property-decorator'

import AnotherComponent from '@/path/to/another-component.vue'

@Component
export default class YourComponent extends Vue {
  @Ref() readonly anotherComponent!: AnotherComponent
  @Ref('aButton') readonly button!: HTMLButtonElement
}

原答案

以上答案都不适用于我想要做的事情。添加以下 $refs 属性最终修复它并似乎恢复了预期的属性。我在这个 github 帖子上找到了链接的解决方案

class YourComponent extends Vue {
  $refs!: {
    vue: Vue,
    element: HTMLInputElement,
    vues: Vue[],
    elements: HTMLInputElement[]
  }

  someMethod () {
    this.$refs.<element>.<attribute>
  }
}
这使我走向正确的方向。我是 vuejs 的新手,不太了解 $ref 的用法,所以对于像我这样的其他人:@Ref('aButton') readonly button!: HTMLButtonElement允许您<button ref="aButton" ... />从脚本中访问元素 wherethis.button.
2021-04-18 18:55:34
const root = ref(null)TypeScript 编译器怎么可能知道root这里的类型是什么?不需要HTMLDivElement显式指定类型 ( ) 吗?
2021-04-18 18:55:34
是的,我相信 vue 的组合 api 的类型是 ref(null) 真的是 ref<HtmlElement|null>(null) 或类似的东西
2021-04-20 18:55:34

这对我有用:使用 (this.$refs.<refField> as any).value(this.$refs.['refField'] as any).value

这清除了错误,但首先破坏了使用typescript的好处。
2021-04-20 18:55:34
强制转换为unknown,然后类型保护转换为您需要的任何其他内容可能更合适unknown更宽容,但仍然进行通常的类型检查,因此更安全。
2021-05-05 18:55:34
没有必要投射任何东西。Aref是 type Vue | Element | Vue[] | Element[],如果这不够具体,您可以使用instanceof运算符来修复类型错误并抛出异常或运行循环或任何其他您需要在运行时根据特定返回类型执行的操作。
2021-05-08 18:55:34
应该 (this.$refs['refField'] as any).value
2021-05-10 18:55:34

儿子.vue

const Son = Vue.extend({
  components: {},
  props: {},
  methods: {
    help(){}
  }
  ...
})
export type SonRef = InstanceType<typeof Son>;
export default Son;

父.vue

<son ref="son" />

computed: {
  son(): SonRef {
    return this.$refs.son as SonRef;
  }
}

//use
this.son.help();
看起来很酷,但方法名称自动完成在 PhpStorm 中对我不起作用:( import VForm from 'vuetify/src/components/VForm/VForm.ts'; type RefVForm = InstanceType<typeof VForm>;
2021-04-23 18:55:34
是的!这正是官方文档所缺少的。为什么我要使用类组件?选项 API 好多了...
2021-05-01 18:55:34
InstanceType<typeof Son> 正是我所需要的。谢谢
2021-05-11 18:55:34
引用自定义组件类型的绝妙方法。这种方式还允许我避免使用类装饰器。
2021-05-14 18:55:34

避免使用括号< >进行类型转换,因为它会与 JSX 冲突。

试试这个

update() {
    const plateElement = this.$refs.plate as HTMLInputElement
    this.$emit('input', { plate: plateElement.value });
}

作为我一直记得的笔记

Typescript 只是具有强大类型功能以确保类型安全的 Javascript。因此(通常)它不会预测 X 的类型(var、param 等),也不会自动对任何操作进行类型转换。

此外,typescript的另一个目的是使 JS 代码变得更清晰/可读,所以总是尽可能定义类型。