Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this value reactive if it's not declared in data?

I need to store some values in a Vue Component beforeCreate hook that I'll require later in beforeDestroy. The thing is (or at least that's what I understood) beforeCreate hook doesn't have access to reactive data yet.

Since I don't need these values anywhere but in beforeDestroy, I don't mind them not being reactive, so I'm good with that. But at the end, when I try:

Vue.component('my-component', {
  data: function() { return { msg: "I'm a reactive value." }},
  template: '<div><div>{{ msg }}</div> <div>{{value}}</div> <button @click="onClick">Click Me</button></div>',
  beforeCreate: function() { this.value = "I was declared before data existed." },
  methods: {
    onClick: function(event) {
      this.msg += " So, I respond to changes.";
      this.value += " But I'm still reactive... (?)";
    }
  }
});

var app = new Vue({
  el: '#app',
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
  <my-component />
</div>

it looks like the value is reactive after all...

  1. What am I missing here?
  2. Is there any possible secondary effect that I should consider when adding data to this in beforeCreate?
like image 713
Jordi Nebot Avatar asked Aug 03 '18 13:08

Jordi Nebot


1 Answers

The reactivity is with this.msg, not this.value

Your confusion seems to come from a misconception about how Vue updates the DOM when reactive data changes:

You seem to think that, if you change this.msg, then Vue would selectively only update those parts of the DOM where msg was used. That's not the case.

What really happens is this:

  1. When any reactive dependency of the template (here: this.msg) changes, the virtualDOM for the whole component is being re-rendered.
  2. This means that in this process, {{ value }} is being re-evaluated, and since you also changed it, its new value is now part of the new virtualDOM.
  3. Then Vue makes a diff of the old and new virtualDOM and patches the real DOM with any changes it found.
  4. Since you changed both {{ msg }} and {{ value }}, both of the <div> elements containing those references will be patched with the new content.

So you see this.value itself is not reactive - but if you change it and also make a reactive change alongside it, the new value will be included in the component's update.

To see that this.value is not reactive, just comment out the change for this.msg:

// this.msg += " So, I respond to changes.";
this.value += " But I'm still reactive... (?)";
like image 200
Linus Borg Avatar answered Oct 03 '22 13:10

Linus Borg