const form = reactive(new T_RAGENCY())
export class T_RAGENCY {
ID:number
updateID = () => {
this.ID++
}
}
form.updateID()
watchEffect 或 watch 无法监听到变化. 页面中双向绑定的值也无法变化.
1
zhaojingfeng OP 有大佬知道怎么解决么
|
2
noe132 2022-04-07 22:19:08 +08:00
你试试在 updateID 把 "this" log 出来看看是什么?
|
3
ymcz852 2022-04-07 22:21:17 +08:00
我猜测是 reactive 返回了一个 T_RAGENCY 实例的代理 proxy 对象(响应式副本),实际上监听的是 proxy 对象 form.updateID() 更新的是原始实例的值,proxy 对象监听不到
|
4
Kiza 2022-04-07 22:25:45 +08:00 via iPhone
我一般不这么用,我找了一个帖子,你看看是否有帮助。https://stackoverflow.com/questions/69050412/vue-composition-api-and-reactive-class
|
6
Kawa 2022-04-07 22:36:19 +08:00 1
不知道你有没有了解过 Proxy 和 Vue toRaw 的原理.
简单的用例大概是这样的: const ProxyObj = Proxy(obj, { get(target, property) { console.log("read: "property); return target[property]; }, set(target, property, value) { console.log("write: "property); target[property] = value; } }); Vue 的 reactive 基本实现原理就是 Proxy. 想象上面 Proxy 的用例, 如果直接对 obj 写入, 那显然不会触发 Proxy 里的 set handler. 如果对 ProxyObj 写入, 那么就会触发 set handler. 同样的道理, 如果你想触发 reactive 的更新, 那么你就需要对 reactive 包裹过的对象执行写入, 而不是对原对象. 而且我认为 reactive 应该仅存数据, 而不应该包括方法. |
7
ymcz852 2022-04-07 22:39:31 +08:00
|
8
Kawa 2022-04-07 22:41:00 +08:00
当然, 如果你非要这样做, 也是有办法的.
比较简单的方法就是做一个 factory, 通过 factory 创建裸对象, 再将其用 reactive 包裹, 最后向其注入 mutation 方法. 非要 new 也不是不行, 可以在类的内部自行维护一个 reactive 对象, 然后定义类属性的 getter 和 setter, 将操作映射到 reactive 对象上. |
9
nomagick 2022-04-07 22:48:33 +08:00
assert(this instanceof T_RAGENCY)
括号函数 this 是在构造的时候决定的,但 vue 拿到你这个对象之后是把上面的属性和方法拿走,舍弃了最初的实例。 之前 vue 就有这个问题,没有维护原型链 |
10
noe132 2022-04-07 22:58:32 +08:00 1
@ymcz852 用了这么久 JS ,我居然把这个搞错了~
这个问题我终于搞明白了。因为 class field 用的是 [[Define]] ( https://github.com/tc39/proposal-class-fields) class { updateId = () => console.log(this) } 相当于 class { constructor(){ Object.defineProperty(this, 'updateId', { value: () => console.log(this), enumerable: true, configurable: true, writable: true }); } } 此时这个方法相当于是在构造函数内定义的,箭头函数内的 this 绑定成了构造函数执行时的 this 。 当 class instance 被 proxy 包了一层后,调用 updateId 拿到的 this 是原对象而不是 proxy ,导致更新没法被检测到。 如果把方法定义成 class method ,this 就是 proxy 。 |
11
zhaojingfeng OP 感谢🙏@Kawa
最后解决方案可行 export class T_RAGENCY { ID:number updateID = () => { this._.ID.value++ } _:UnwrapNestedRefs<any> } form._ = {...toRefs(form)} |
12
Curtion 2022-04-08 10:09:55 +08:00
|
14
daolanfler 2022-04-08 13:50:59 +08:00
|
15
dreamerblue 2022-04-08 22:39:26 +08:00
一看看到箭头函数就猜到会出问题...不知道是不是从 React 类组件带过来的习惯?写 Vue 就用最符合直觉的方式去定义方法就好了,无论是写选项式组件还是类组件 /服务都是一样的。
|