Vue3+TypeScript中如何让对象方法修改的状态同步到页面?
解决Vue3中TypeScript类状态修改无法触发页面同步的问题
问题描述
使用Vue3 + TypeScript开发Web应用,将纯TS对象与Vue组件分离,通过OperationManager管理Operation实例,Operation类包含PENDING/IN_PROGRESS/FINISHED状态。调用Operation.next()修改状态后,页面未同步更新状态。
问题根源
普通TypeScript类实例不属于Vue的响应式对象,Vue的Proxy无法追踪其内部属性的变化,因此状态修改不会触发视图更新。
解决方案
方案1:将Operation实例转为响应式对象
在创建Operation实例时,用reactive包裹,让Vue追踪其属性变化:
修改App.vue:
<script setup lang="ts"> import { reactive, ref } from 'vue'; import Operation from './Operation'; import OperationListItem from './OperationListItem.vue'; import OperationManager from './OperationManager'; const opManager = reactive(new OperationManager()); const log = ref(""); // 用reactive包装Operation实例 const op = reactive(new Operation()); opManager.put(op); const sleep = (ms: number) => new Promise(r => setTimeout(r, ms)); sleep(2000).then(_ => {op.next(); log.value += "next" }) </script>
方案2:让Operation内部使用响应式状态
在Operation类内部用ref定义状态,使状态本身具备响应式能力:
修改Operation.ts:
import { ref } from 'vue'; export default class Operation { state = ref<"PENDING" | "IN_PROGRESS" | "FINISHED">("PENDING"); async next() { switch (this.state.value) { case "PENDING": this.state.value = "IN_PROGRESS"; break; case "IN_PROGRESS": this.state.value = "FINISHED"; break; case "FINISHED": break; } } }
修改OperationListItem.vue模板,访问响应式状态的value属性:
<template> <div> {{ operation.state.value }} </div> </template>
方案3:在OperationManager中统一管理响应式实例
让OperationManager内部维护响应式数组,并确保存入的Operation实例是响应式的:
修改OperationManager.ts:
import { reactive } from 'vue'; import Operation from "./Operation"; export default class OperationManager { private _operations = reactive<Operation[]>([]); put(operation: Operation) { // 存入前转为响应式对象 this._operations.push(reactive(operation)); } get operations() { return this._operations; } }
原理说明
Vue3通过ES6 Proxy实现响应式系统,仅对reactive/ref包装的对象进行属性拦截与变化追踪。将Operation的状态或实例纳入Vue的响应式系统后,属性修改会触发Proxy的拦截逻辑,进而通知Vue更新视图。
内容的提问来源于stack exchange,提问作者Eva
相关产品推荐
相关产品推荐

