You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue如何实现自定义类实例属性变更后触发视图更新

问题原因

  • 你当前创建的Stopwatch是普通类实例,没有被Vue的响应式系统代理,实例内部属性变更时Vue无法感知,自然不会触发视图更新
  • 你使用computed包裹类实例的写法属于API误用,computed适用于依赖其他响应式变量动态计算值的场景,这里不需要额外包裹

最优解决方案(无侵入,类代码无需修改)

直接用reactive包裹类实例即可,修改main.vue的setup逻辑:

<script lang="ts">
import {
  defineComponent,
  reactive
} from '@vue/composition-api';
import Stopwatch from 'src/utils/stopwatch';

export default defineComponent({
  // 注意修改组件名,避免和导入的Stopwatch类重名冲突
  name: 'StopwatchPage',
  setup() {
    // 用reactive包裹类实例,让实例属性变为响应式
    const sw = reactive(new Stopwatch());
    return {
      sw
    };
  }
});
</script>

方案说明

  • reactive会将普通类实例转为Vue的响应式代理对象,所有在constructor中提前声明的属性变更都会被Vue跟踪,自动触发视图更新
  • 类的原有方法完全不需要修改,方法内修改this属性的逻辑会自动作用于响应式代理对象,变更可被正常捕获

备选方案(类与Vue耦合,适合仅在Vue项目中使用的场景)

如果你接受类和Vue响应式API绑定,可以直接在类内部用ref声明响应式属性,无需在使用时包裹:
修改stopwatch.ts:

import { ref } from '@vue/composition-api'
export default class Stopwatch {
  // 直接用ref定义响应式属性
  isPlaying = ref<boolean>(false);

  constructor() {}

  startTimer() {
    this.isPlaying.value = true;
    console.log('play');
  }

  stopTimer() {
    this.isPlaying.value = false;
    console.log('stop');
  }

  toggle() {
    if (this.isPlaying.value) {
      this.stopTimer();
    } else {
      this.startTimer();
    }
  }
}

对应的main.vue里直接初始化实例即可:

setup() {
  const sw = new Stopwatch();
  return { sw };
}

注意事项

如果后续要给Stopwatch类扩展新属性,必须在类的constructor中提前声明该属性的初始值,否则Vue2的响应式系统无法跟踪后续新增的属性变更。

内容的提问来源于stack exchange,提问作者JokerMartini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 20:45:03