将类实例赋值给Vue响应式ref报错的原因及解决方案
问题描述
实例化WSFetchNDVIsTIFFResponses类对象并赋值给响应式ref #wsFetchNDVIsTIFFResponses时,以下代码触发Promise的.catch回调:
this.#wsFetchNDVIsTIFFResponses.value = new WSFetchNDVIsTIFFResponses(); this.#wsFetchNDVIsTIFFResponses.value.setResponse(response);
但改为以下写法后可正常运行:
new WSFetchNDVIsTIFFResponses().setResponse(response);
需要分析file.js代码报错的原因及修复方法。
相关代码
file.js
constructor(clsDigitizationPolygonInteractionsInst) { this.#wsFetchNDVIsTIFFResponses = ref(null); } this.#wsSentinelhubEngineProcessor.fetchNDVIsTIFF(res => { const response = JSON.parse(res); this.#wsFetchNDVIsTIFFResponses.value = new WSFetchNDVIsTIFFResponses(); this.#wsFetchNDVIsTIFFResponses.value.setResponse(response); return response; }) .then(res => {
WSFetchNDVIsTIFFResponses类
export class WSFetchNDVIsTIFFResponses { #msg = null; #response = null; constructor() { this.#response = ref(null); } setResponse(res) { this.#response.value = res; } }
报错原因
Vue响应式系统在给ref赋值对象时,会对对象进行深度响应式转换。当你把WSFetchNDVIsTIFFResponses实例赋值给#wsFetchNDVIsTIFFResponses.value时,Vue会遍历实例的所有属性,包括私有字段#response。
但私有字段#response只能在类内部访问,Vue的响应式转换代码在外部尝试访问这个私有字段时,会直接抛出私有字段访问权限错误,这个错误被Promise的.catch捕获,导致回调触发。
而直接调用new WSFetchNDVIsTIFFResponses().setResponse(response)时,实例没有被赋值给响应式ref,Vue不会对它做响应式转换,也就不会触发私有字段的访问权限问题,因此能正常运行。
修复方法
提供两种可行方案:
方案一:阻止Vue对类实例做响应式转换
使用markRaw标记实例,告诉Vue不要对其进行响应式转换,保留私有字段的访问权限:
import { markRaw } from 'vue'; // 赋值时用markRaw包裹实例 this.#wsFetchNDVIsTIFFResponses.value = markRaw(new WSFetchNDVIsTIFFResponses()); this.#wsFetchNDVIsTIFFResponses.value.setResponse(response);
方案二:修改类的实现逻辑
如果不需要类内部的#response是响应式的,可将其改为普通变量:
export class WSFetchNDVIsTIFFResponses { #msg = null; #response = null; constructor() { this.#response = null; // 移除ref,改为普通变量 } setResponse(res) { this.#response = res; } }
若确实需要#response保持响应式,可以将其改为公开属性,或者用reactive包裹整个实例(注意私有字段的访问限制)。
内容的提问来源于stack exchange,提问作者Amr
相关产品推荐
相关产品推荐

