javascript - Varför är detta värde reaktivt om det inte deklareras i data?


Jag behöver lagra några värden i en Vue-komponents beforeCreate-hook som jag kommer att behöva senare i beforeDestroy. Grejen är (eller åtminstone vad jag förstod) att beforeCreate-hooken ännu inte har tillgång till reaktiv data.

Eftersom jag inte behöver dessa värden någon annanstans än i beforeDestroy, har jag inget emot att de inte är reaktiva, så det är okej för mig. Men i slutet, när jag försöker:

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>

det ser ut som att värdet är reaktivt trots allt...

  1. Vad missar jag här?
  2. Finns det någon möjlig sekundär effekt som jag bör överväga när jag lägger till data i this i beforeCreate?

Svar #1

Reaktiviteten är med this.msg, inte this.value

Din förvirring verkar komma från en missuppfattning om hur Vue uppdaterar DOM när reaktiv data ändras:

Du verkar tro att om du ändrar this.msg så skulle Vue selektivt bara uppdatera de delar av DOM där msg användes. Så är det inte.

Vad som verkligen händer är detta:

  1. När något reaktivt beroende i mallen (här: this.msg) ändras, renderas virtualDOM för hela komponenten om.
  2. Detta innebär att i denna process utvärderas {{ value }} på nytt, och eftersom du också ändrade det, är dess nya värde nu en del av den nya virtualDOM.
  3. Sedan gör Vue en diff av det gamla och nya virtualDOM och uppdaterar den verkliga DOM med eventuella förändringar den hittade.
  4. Eftersom du ändrade både {{ msg }} och {{ value }}, kommer båda <div>-elementen som innehåller dessa referenser att uppdateras med det nya innehållet.

Så du ser, this.value i sig är inte reaktivt - men om du ändrar det och också gör en reaktiv förändring samtidigt, kommer det nya värdet att inkluderas i komponentens uppdatering.

För att se att this.value inte är reaktiv, kommentera bara ut ändringen för this.msg:

// this.msg += " So, I respond to changes.";
this.value += " But I'm still reactive... (?)";