我有一个类Thing,它的构造函数启动异步fetch操作.fetch完成后,结果将分配给Thing对象上的字段:

  class Thing {
    constructor() {
      this.image = null
      this.load()
    }

    async load() {
      const response = await fetch('https://placekitten.com/200/300')
      const blob = await response.blob()
      this.image = await createImageBitmap(blob)
    }
  }

我在Vue组件中使用thing.image.问题是,当Promise解决时,Vue无法识别image中的变化.我想我理解为什么会发生这种情况:在构造函数中,this指的是原始Thing,而不是Vue的react 式代理包装器.因此,对this.image的赋值最终绕过了代理.

如果我将load调用移出构造函数,那么它就可以工作,因此load函数中的this引用了react 式代理.但这让我的Thing课更难使用.

有没有更好的方法来处理这个问题?

最小示例(Vue playground link):

<script setup>
  import { reactive } from 'vue'

  class Thing {
    constructor() {
      this.image = null
      this.load() // This does not trigger reactivity.
    }

    async load() {
      const response = await fetch('https://placekitten.com/200/300')
      const blob = await response.blob()
      this.image = await createImageBitmap(blob)
    }
  }

  const thing = reactive(new Thing())
  // thing.load() // This triggers reactivity as expected.
</script>

<template>
  <p v-if="thing.image">
    Image size is {{thing.image.width}}×{{thing.image.height}}
  </p>
  <p v-if="!thing.image">
    Loading...
  </p>
</template>

推荐答案

将类属性定义为ref

<script setup>
  import { reactive, ref } from 'vue'

  class Thing {
    constructor() {
      this.image = ref(null)
      this.load()
    }

    async load() {
      const response = await fetch('https://placekitten.com/200/300')
      const blob = await response.blob()
      this.image.value = await createImageBitmap(blob)
    }
  }

  const thing = reactive(new Thing())
  // thing.load() // This triggers reactivity as expected.
</script>

<template>
  <p v-if="thing.image">
    Image size is {{thing.image.width}}×{{thing.image.height}}
  </p>
  <p v-if="!thing.image">
    Loading...
  </p>
</template>

Javascript相关问答推荐

如何使用React渲染器放置根dis?

我的glb文件没有加载到我的three.js文件中

如何解决这个未能在响应上执行json:body stream已读问题?

将2D数组转换为图形

在这种情况下,如何 for each 元素添加id?

如何修复(或忽略)HTML模板中的TypeScript错误?'

v—自动完成不显示 Select 列表中的所有项目

无法读取未定义错误的属性路径名''

如何在Bootstrap中减少网格系统中单个div的宽度

使用插件构建包含chart.js提供程序的Angular 库?

如何确保预订系统跨不同时区的日期时间处理一致?

Reaction-SWR-无更新组件

未捕获语法错误:Hello World中的令牌无效或意外

判断函数参数的类型

与在编剧中具有动态价值的定位器交互

我为什么要使用回调而不是等待?

需要从对象生成列表

带元素数组的Mongo聚合

带有JS模块模式的Rails的Importmap错误:";Net::ERR_ABORTED 404(未找到)&Quot;

使用JavaScript或PHP从div ID值创建锚标记和链接