-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error when property value is an instance of a class using private class fields #8149
Comments
import { createApp, shallowRef, toRaw, markRaw } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
class Foo {
#bar = 1;
get bar() {
return this.#bar;
}
}
createApp({
data() {
return {
foo: shallowRef(new Foo()) // or toRaw, but it's loses reactivity 🫠
}
},
mounted() {
console.log(this.foo)
}
}).mount("#app"); Vue transfer Option API: Proxy { foo: object } Composition API: Proxy { foo: RefImpl } |
In order for Vue to properly track property access inside object / class instance methods, If we use the original object as In general, we recommend using plain objects over class instances as data sources. If you really need encapsulation and only expose certain reactive state, consider using Composition API and using Composables. |
I assume you need immutable object properties (private ones in JS case) for well-known reasons. There is a workaround for Vue. In the private property accessor (a JS getter) unwrap the proxy and access the property on the raw object. import { createApp, isProxy, toRaw } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
// ...
get bar() {
return isProxy(this) ? toRaw(this).#bar : null; // Just an example. Treat the values as per concrete use case.
} This works with both Options and Composition APIs.
@LeaVerou Can you clarify what workaround you meant here. Thanks. |
@WhereJuly Your workaround requires coupling Vue with the class using the private properties, however these may be developed entirely separately. E.g. in my case, I was handling |
@LeaVerou True, my workaround requires coupling with Vue. For code assumed to work along with Vue it is fine, though for code trying to be Vue-agnostic this is the problem. Could be probably solved by some Vue-aware adapter object nearby the original object to still keep properties private. Though this approach applicability and usefulness depends a lot on a paricular use case. However in your initial post you mentioned there is the other workaround that can be used in the proxy traps. It sounds really intersting. Could you explain what it is or give a reference? Thanks. |
Vue version
3.2.47
Link to minimal reproduction
https://codepen.io/leaverou/pen/MWPpEQg?editors=1011
Steps to reproduce
Visit testcase
What is expected?
1 in Result pane
What is actually happening?
Error
System Info
Any additional comments?
Apparently proxies break private class fields (MDN, non-Vue testcase). This means that every time an instance of a class using private fields is used as the value of a Vue property, things break (see testcase). Since there is a workaround that can be used in the proxy traps, I'd consider this a Vue bug.
Vue was mentioned several times in tc39/proposal-class-fields#106 , so I'd be surprised if this is not known, but I couldn't find an existing issue, so opening this just in case.
The text was updated successfully, but these errors were encountered: