如何使用 Vue 类组件访问 VueJS 3 和 Typescript 中的 HTML ref?

问题描述

我正在解决以下问题:我使用 Vue 3 和 Typescript 创建了一个 QRCode 组件,代码如下:

<template>
  <canvas ref="qrcodeVue"> </canvas>
</template>

<script lang="ts">
import QRCode from "qrcode";
import { Vue,Options } from "vue-class-component";
import { ref } from "vue";

@Options({
  props: {
    value: {
      type: String,required: true
    },size: {
      type: [Number,String],validator: (s: [number | string]) => isNaN(Number(s)) !== true
    },level: {
      type: String,validator: (l: string) => ["L","Q","M","H"].indexOf(l) > -1
    },background: String,foreground: String
  }
})
export default class QRCodeVue extends Vue {
  value = "";
  size: number | string = 100;
  level: "L" | "Q" | "M" | "H" = "L";
  background = "#ffffff";
  foreground = "#0000ff";

  mounted() {
    const _size = Number(this.size);
    const scale = window.devicePixelRatio || 1;
    const qrcodeVue = ref<HTMLCanvasElement | null>(null);

    QRCode.toCanvas(qrcodeVue,this.value,{
      scale: scale,width: _size,color: { dark: this.foreground,light: this.background },errorCorrectionLevel: this.level
    });
  }
}
</script>

但是 qrcodeVue 总是指什么都没有,我永远无法访问画布本身。我错过了什么?我应该把这个 ref() 代码放在哪里?我也试过 defineComponent 得到相同的结果。感谢您提供任何线索。

(顺便说一句,我也尝试使用 npm qrcode-vue 包,但它似乎不支持 Vue 3)

解决方法

您必须首先将 ref qrcodeVue 声明为类属性,而不是在 mounted 内。

只有到那时它才可用并填充 mounted 中的 ref 元素:

export default class QRCodeVue extends Vue {
  qrcodeVue = ref<HTMLCanvasElement | null>(null); // not inside mounted

  mounted() {
    console.log(this.qrcodeVue);  // now it's available
  }
}

这等效于以下 Vue 3 setup 语法:

setup() {
  const qrcodeVue = ref(null);
  onMounted(() => {
    console.log(qrcodeVue.value);
  })
  return {
    qrcodeVue
  }
}