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

为何Vue data中带私有字段的类实例调用方法触发私有字段赋值报错

问题原因

这是正常现象。

Vue的响应式系统会对data函数返回的所有属性做响应式转换:Vue 3 会将对象包装为 Proxy 代理,Vue 2 会通过Object.defineProperty重写属性的读写逻辑。你将Foo类的实例声明在data中时,后续通过this.foo拿到的不是原始的类实例,而是经过响应式处理的代理对象。

而JavaScript的私有类字段有严格的访问限制:仅能在类内部访问,且只能作用于类的原始实例,代理对象、继承实例等非原始实例都无法读写私有字段。你调用this.foo.init(2)时,init方法内部的this指向的是响应式代理,不是原始Foo实例,因此触发了私有字段的访问报错。你在mounted中定义局部变量存储实例时,用到的是原始实例没有被代理,所以可以正常运行。

解决方案

方案1:不将类实例放入data

直接将类实例挂载到组件实例上,不要在data中声明,就不会被Vue做响应式处理:

<template>
  <div class="hello">
    <div>{{bar}}</div>
  </div>
</template>

<script>
import Foo from '../api/foo.js';
export default {
  created() {
    // 直接挂载到this,不进入响应式处理流程
    this.foo = new Foo()
  },
  data(){
    return {
      bar: '',
    }
  },
  mounted() {
    this.foo.init(2);
    this.bar = this.foo.getBar();
  },
}
</script>

方案2:用markRaw标记实例跳过响应式处理(Vue 3适用)

如果需要将实例放在data中,可以用Vue提供的markRaw方法标记实例,告知Vue不需要对其做响应式转换:

<template>
  <div class="hello">
    <div>{{bar}}</div>
  </div>
</template>

<script>
import { markRaw } from 'vue'
import Foo from '../api/foo.js';
export default {
  data(){
    return {
      // markRaw标记后不会被转为响应式代理
      foo: markRaw(new Foo()),
      bar: '',
    }
  },
  mounted() {
    this.foo.init(2);
    this.bar = this.foo.getBar();
  },
}
</script>

内容的提问来源于stack exchange,提问作者Raphaël

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:48:01