web-dev-qa-db-fra.com

VueJs, différence entre la propriété calculée et l'observateur?

Dans la documentation de Vue.js, vous trouverez un exemple comme ci-dessous:

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})

Le code ci-dessus est impératif et répétitif. Comparez-le avec une version de propriété calculée:

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

Quelles sont les situations où les observateurs sont plus appropriés que les propriétés calculées? Comment devrais-je décider lequel choisir? La documentation continue à dire qu'il est plus "générique" mais ne dit pas vraiment son but.

36
serkan

Propriétés calculées

Un exemple de propriété calculé:

computed: {
   val () {
     return this.someDataProperty * someOtherVariable
   }
}

que fait ce code en particulier?

  1. Il crée une propriété nommée val pour le composant. (sur le prototype, donc <vueInstanece>.hasOwnProperty('val') afficherait false).

  2. Il a un arbre de dépendance qui consiste en propriétés réactives (propriétés de données, autres propriétés calculées) dans ce cas: this.someDataProperty, Ce qui signifie Au moment où les dépendances changent, la propriété calculée sera recalculée.

  3. Bien que débattu, aucun argument ne peut y être transmis. Donc quelque chose comme

    computed: {
      val (flag) {
        return (flag === 1) 
          ? this.someDataProperty * someOtherVariable 
          : this.someDataProperty * 5
        }
    }
    

    ne peut pas être fait

[EDIT] Voir: https://vuejs.org/v2/guide/computed.html#Computed-Setter

Observateur

Un échantillon d'observateur:

watch: {
   val (n, o) {
     console.log(n, o)
   }
}
  1. Il ne crée aucune nouvelle propriété, mais il surveille les modifications d'une propriété réactive.

  2. Ne surveille qu'une propriété spécifique, contrairement au calcul où toute modification de propriété dépendante peut provoquer un recalcul.

  3. A des arguments de valeur nouvelle et ancienne.


Donc les propriétés calculées seraient la voie à suivre si:

Vous voulez toujours une propriété qui dépend d'autres propriétés. Comme la mise en forme de texte pour un modèle, qui est même l'exemple de votre code.

Ou réduire les longueurs variables car c'est assez courant:

this.$store.state.someProperty.someNestedProperty.someDeeplyNestedProperty

peut être réduit à:

computed: {
  someDeeplyNestedProperty () {
     return this.$store.state.someProperty.someNestedProperty.someDeeplyNestedProperty
  }
}

Non seulement la réduction de la taille des variables, à chaque fois que le magasin se met à jour, vous aurez la dernière valeur dans le fichier someDeeplyNestedProperty.


Et Les observateurs sont utiles si vous voulez voir si une propriété réactive a été remplacée par une valeur favorable pour savoir que vous êtes prêt à exécuter une action.

comme:

watch: {
  somethingSelected() {
    this.router.Push('someOtherRoute')
  }
}

[~ # ~] edit [~ # ~] : Je suis tombé sur un bon article de Flavio Copes qui a énuméré l'usage courant cas pour chacun d’eux (méthodes, accessoires calculés, observateurs):

Quand utiliser des méthodes

  • Réagir sur un évènement se déroulant dans le DOM

  • Appeler une fonction lorsque quelque chose se passe dans votre composant. Vous pouvez appeler des méthodes à partir de propriétés calculées ou d’observateurs.

Quand utiliser les propriétés calculées

  • Vous devez composer de nouvelles données à partir de sources de données existantes
  • Dans votre modèle, vous utilisez une variable construite à partir d'une ou de plusieurs propriétés de données.
  • Vous souhaitez réduire un nom de propriété complexe et imbriqué à un nom plus lisible et facile à utiliser, tout en le mettant à jour lorsque la propriété d'origine change
  • Vous devez référencer une valeur du modèle. Dans ce cas, la création d’une propriété calculée est la meilleure solution car elle est mise en cache.
  • Vous devez écouter les modifications de plusieurs propriétés de données.

Quand utiliser les observateurs

  • Vous voulez écouter quand une propriété de données change et effectuer une action
  • Vous voulez écouter un changement de valeur de prop
  • Vous devez uniquement écouter une propriété spécifique (vous ne pouvez pas regarder plusieurs propriétés en même temps).
  • Vous voulez regarder une propriété de données jusqu'à ce qu'elle atteigne une valeur spécifique, puis faire quelque chose
38
Amresh Venugopal

Les propriétés calculées ont un objectif très spécifique: composer de nouvelles données dérivées d'autres données. Ils sont utilisés chaque fois que vous avez des données et que vous devez les transformer, les filtrer ou les manipuler d'une autre manière avant de les utiliser dans le modèle.

Les propriétés calculées doivent toujours renvoyer une valeur, ne doivent avoir aucun effet secondaire et doivent être synchrones.

Ainsi, dans certaines situations, les propriétés calculées ne vous aident pas, par exemple: votre composant reçoit un accessoire, et chaque fois que celui-ci change, votre composant doit faire une demande ajax. Pour cela, vous auriez besoin d'un observateur.

Les observateurs ne sont pas aussi utiles que les propriétés calculées. Vous devez donc toujours vous demander si une propriété calculée peut résoudre votre problème et ne faire appel à un observateur (ou parfois à une méthode) si ce n'est pas le cas.

22
Linus Borg

Vue.js est réactif

Cela signifie qu'il est capable de réagir à des choses telles que les saisies utilisateur et les modifications de données. Je recommande de lire sur le système de réactivité pour mieux comprendre la mécanique utilisée par Vue sous le capot lorsqu'un changement de données est observé. Il existe trois méthodes principales pour que vos composants exploitent la nature réactive de Vue. Ce sont les méthodes, les propriétés calculées et les observateurs. Sans un examen minutieux, ces options peuvent sembler interchangeables (et à certains égards, elles le sont), mais chacune d’elles a son meilleur scénario d’utilisation. Pour illustrer ces exemples, je vais créer une petite application d'évaluation qui permet à un enseignant de saisir les résultats des tests des élèves de sa classe, d'afficher la note moyenne et de configurer l'échafaudage pour une fonction de sauvegarde automatique.

MÉTHODES

TL; DR - Utilisez des méthodes lorsque vous souhaitez modifier l'état d'un composant ou lorsqu'un événement survient qui n'est pas nécessairement lié aux données d'instance en cours de mutation . . Les méthodes peuvent prendre des arguments mais ne gardent aucune trace de dépendances. Lorsque vous utilisez une méthode, elle crée généralement un effet secondaire au sein du composant et les méthodes sont exécutées à chaque rechargement du composant. Cela signifie que si l'interface utilisateur est mise à jour très fréquemment, cette méthode (et toutes les autres méthodes du composant) sera également exécutée. Cela pourrait entraîner des problèmes de performances ou des retards dans l'interface utilisateur.

Ci-dessous, le début de notre application de classement. Il n'y a pas de validation ou quoi que ce soit et ce n'est pas joli, je sais. Nous avons un petit ensemble de tests dans notre objet de données (nom et score de l’étudiant). Et une méthode que nous pouvons utiliser pour ajouter un autre objet de test à notre propriété de données ‘tests’.

new Vue({
  el: "#app",
  data: {
    newTest: {
      studentName: '',
      score: 0
    },
    tests: [{
      studentName: "Billy",
      score: 76
    }, {
      studentName: "Suzy",
      score: 85
    }, {
      studentName: "Johnny",
      score: 89
    }, {
      studentName: "Emma",
      score: 93
    }]
  },
  methods: {
    addTestScore: function() {
      this.tests.Push({
        studentName: this.newTest.studentName,
        score: this.newTest.score
      });
      this.newTest.studentName = '';
      this.newTest.score = 0;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<body>
  <div id="app">
    <ul>
      <li v-for="test in tests">
        {{test.studentName}} - {{test.score}}
      </li>
    </ul>
    <span>Student</span>
    <input v-model="newTest.studentName">
    <span>Score</span>
    <input v-model="newTest.score">
    <button @click="addTestScore">Add </button>
  </div>
</body>

PROPRIÉTÉS INFORMATIQUES

TL; DR - Utilisez une propriété calculée lorsque vous souhaitez muter une propriété qui dépend d'une autre propriété en cours de modification. Les propriétés calculées dépendent généralement d'autres données. Propriétés. Toute modification des propriétés dépendantes déclenchera la logique de la propriété calculée. Les propriétés calculées sont mises en cache en fonction de leurs dépendances. Elles ne seront donc réexécutées que si une dépendance est modifiée. (Par exemple, une propriété calculée qui renvoie une nouvelle date () ne sera jamais réexécutée car la logique ne s'exécutera jamais plus d'une fois.) Les propriétés calculées sont des getters par défaut, mais une fonction de définition peut être définie si nécessaire pour obtenir des fonctionnalités similaires.

Dans notre application de notation, nous voulons garder une trace du score moyen au test à mesure que nous entrons plus de données. Ajoutons une propriété calculée appelée "moyenne" qui renverra le score moyen des tests de notre jeu de données. La propriété calculée "moyenne" sera mise à jour chaque fois que nous ajouterons un autre score au test.

new Vue({
  el: "#app",
  data: {
    newTest: {
      studentName: '',
      score: 0
    },
    tests: [{
      studentName: "Billy",
      score: 76
    }, {
      studentName: "Suzy",
      score: 85
    }, {
      studentName: "Johnny",
      score: 89
    }, {
      studentName: "Emma",
      score: 93
    }]
  },
  computed: {
    average: function() {
      var sum = this.tests.reduce(function(acc, test) {
        return acc + Number(test.score);
      }, 0);
      return (sum / this.tests.length).toFixed(2);
    }
  },
  methods: {
    addTestScore: function() {
      this.tests.Push({
        studentName: this.newTest.studentName,
        score: this.newTest.score
      });
      this.newTest.studentName = '';
      this.newTest.score = 0;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>

<body>
  <div id="app">
    <span>Average Score: {{average}}</span>
    <ul>
      <li v-for="test in tests">
        {{test.studentName}} - {{test.score}}
      </li>
    </ul>
    <span>Student</span>
    <input v-model="newTest.studentName">
    <span>Score</span>
    <input v-model="newTest.score">
    <button @click="addTestScore">Add</button>
  </div>
</body>

OBSERVATEURS

TL; DR - Utilisez les observateurs lorsque vous devez exécuter une logique suite à une modification apportée à une propriété de données spécifique . Les propriétés surveillées n'agissent que sur une propriété. Ceci est particulièrement utile lorsque vous souhaitez effectuer des opérations asynchrones ou coûteuses en réponse à la modification des données. Gardez à l'esprit que les observateurs ne changent que lorsque cette propriété de données spécifique change.

Supposons que l'utilisateur final de notre petite application de notation est un professeur avec 300 tests à évaluer. Cela peut prendre beaucoup de temps. Une fonctionnalité de sauvegarde automatique serait agréable si notre utilisateur final arrive à la fin de la pile de tests et oublie de cliquer manuellement sur enregistrer. Dans notre code, ajoutons un observateur à notre propriété calculée précédemment ‘moyenne’. Chaque fois qu’elle est modifiée (à la suite de l’ajout d’un nouveau score au test et de la mise à jour de la moyenne), appelons une nouvelle méthode de “sauvegarde automatique” qui peut être utilisée pour appeler une API et enregistrer nos scores de test.

new Vue({
  el: "#app",
  data: {
    newTest: {
      studentName: '',
      score: 0
    },
    tests: [{
      studentName: "Billy",
      score: 76
    }, {
      studentName: "Suzy",
      score: 85
    }, {
      studentName: "Johnny",
      score: 89
    }, {
      studentName: "Emma",
      score: 93
    }]
  },
  watch: {
    average: function() {
      this.autosave();
    }
  },
  computed: {
    average: function() {
      var sum = this.tests.reduce(function(acc, test) {
        return acc + Number(test.score);
      }, 0);
      return (sum / this.tests.length).toFixed(2);
    }
  },
  methods: {
    addTestScore: function() {
      this.tests.Push({
        studentName: this.newTest.studentName,
        score: this.newTest.score
      });
      this.newTest.studentName = '';
      this.newTest.score = 0;
    },
    autosave: function() {
    //pretend we are calling our backend to save the data
      console.log('calling api, saving data');
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<body>
  <div id="app">
    <span>Average Score: {{average}}</span>
    <ul>
      <li v-for="test in tests">
        {{test.studentName}} - {{test.score}}
      </li>
    </ul>
    <span>Student</span>
    <input v-model="newTest.studentName">
    <span>Score</span>
    <input v-model="newTest.score">
    <button @click="addTestScore">Add</button>
  </div>
</body>
9
Humoyun Ahmad

Pour les besoins de cet exemple, les propriétés calculées sont en effet meilleures. Dans l'exemple qui utilise les observateurs, notez que cette ligne de code:

this.fullName = this.firstName + ' ' + val

est très similaire à ceci:

this.fullName = val + ' ' + this.lastName

Les deux servent le même objectif, ils surveillent les changements du prénom ou du nom et mettent à jour fullName en conséquence. Mais comme cela ne changera jamais et que fullName sera toujours composé par firstName et lastName, nous pourrons alors éviter les complications et créer une propriété calculée. Puis à chaque fois firstName et lastName changer, fullName sera mis à jour automatiquement.

Cependant, dans certains cas, l’utilisation d’observateurs est préférable. Lorsque vous voulez faire un calcul sérieux d'écriture de code async, un observateur peut être plus approprié.

Par exemple, si vous aviez quelque chose comme ceci:

let app = new Vue({
    el: '#app',
    data: {
        name: ""
    }
});

Et vous voulez, chaque fois que name change, faire un appel API avec elle, obtenir le résultat et le traiter, un observateur est plus approprié:

watchers: {
    "name": function(newValue, oldValue){
         if(newValue != oldValue)} {
            fetch(url, {method: 'post', body: JSON.stringify({name: this.name})}).then(...);
        }
    }
}

Pour faire cela avec une propriété calculée, vous devez implémenter une propriété computed get() et une propriété computed set() qui donneraient plus de code.

Notez également que dans l'exemple de la documentation, nous avons une propriété, fullName qui est composée a.k.a calculée par deux autres propriétés. Dans mon exemple, name n'est pas calculé, au sens littéral du terme. Nous voulons simplement l'observer, donc utiliser une propriété calculée serait plus un hack que un motif.

2
dimlucas

Vous utilisez un observateur lorsque vous souhaitez modifier une valeur ou effectuer une action en fonction de la modification d'une autre valeur. Un bon exemple de cela est lorsque vous définissez une valeur basée sur un accessoire et que vous souhaitez réagir à tout changement:

Vue.component('my-comp',{
  template: '#my-comp',
  props: ['username'],
  created() {
    this.user = this.username;
  },
  watch:{
    username(val){
      this.user = val;
    }
  },
  data(){
    return{
      user: ''
    }
  }
});

Voir ce JSFiddle: https://jsfiddle.net/fjdjq7a8/

Cet exemple est un peu artificiel et ne fonctionne pas vraiment dans le monde réel car nous ne synchronisons pas les valeurs. Voici donc un exemple réel dans lequel je l'utilise dans l'un de mes projets open source :

Les calculs permettent de manipuler les données elles-mêmes de manière arbitraire, par exemple pour concaténer des chaînes et calculer des valeurs.

2
craig_h

regarder

Utilisez watch lorsque vous souhaitez effectuer des opérations asynchrones ou coûteuses en réponse à la modification des données.

calculé

Utilisez calculé dans d'autres cas. Les propriétés calculées sont mises en cache en fonction de leurs dépendances. Généralement utilisé lorsque vous ne souhaitez réévaluer que certaines de ses dépendances ont été modifiées.

1
Bhojendra Rauniyar