vue-class-store icon indicating copy to clipboard operation
vue-class-store copied to clipboard

Preserving `this` identity (Vue 2)

Open thecodewarrior opened this issue 2 years ago • 0 comments

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 avatar Nov 04 '21 18:11 thecodewarrior