Skip to content
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

Preserving this identity (Vue 2) #28

Open
thecodewarrior opened this issue Nov 4, 2021 · 0 comments
Open

Preserving this identity (Vue 2) #28

thecodewarrior opened this issue Nov 4, 2021 · 0 comments

Comments

@thecodewarrior
Copy link

thecodewarrior commented Nov 4, 2021

Background

One of the trickiest pitfalls with Vue reactivity is the fact that adding reactivity involves wrapping an object. The original object isn't reactive, only the wrapper created with new Vue({data: {...}}).

let original = {wow: 10};
let reactive = new Vue({data: original});
original.wow = 20; // this doesn't cause reactions

When using @VueStore this becomes a problem if you capture this in the constructor:

@VueStore
class AsyncStore {
  value: string = null

  constructor(id) {
    requestData(id).then((v) => {
      this.value = v; // the captured `this` refers to the original, not the reactive wrapper
    });
  }
}

Proposal

It would be great if we could inject reactivity into the original object, that way the captured this would be reactive. #27 is my implementation of this.

Implementation

The principle behind my solution is double-initializing the object. After the store is constructed we rip out the data, then we turn around and ask Vue to initialize this now-empty object with the extracted data.

In order to do this we have to extend Vue while not extending the Vue constructor. If we extended the constructor, Vue would initialize the object before we get a chance to add our data.

Details

The way I implement this quasi-inheritance is that, instead of having Vue in the prototype chain, I literally copy the contents of the Vue prototype into the store's prototype.

The double-initialization is feasible because the Vue constructor just calls this._init(options). Because we copied the prototype, all we have to do is take the initialized store, rip out the data, then call store._init({data: extractedData}).

Vue 3

See #29

It might be worth emulating the Vue 3 API limitations with regard to inheritance. i.e. we could require you subclass VueStore to get the new this safety, to ease the transition to Vue 3.

@thecodewarrior thecodewarrior changed the title Adding reactivity to an existing object (Vue 2) Preserving this identity (Vue 2) Nov 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant