62 votes

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.

76voto

Amresh Venugopal Points 3846

Les Propriétés Calculées

Une propriété calculée de l'échantillon:

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

quel est ce morceau de code?

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

  2. Il a un arbre de dépendances qui se compose de réactif propriétés (propriétés de données, d'autres propriétés calculées) dans ce cas : this.someDataProperty, ce qui signifie que le moment où les dépendances du changement, la propriété calculée sera recalculé.

  3. Bien que controversée, ne peut pas avoir des arguments passés. Donc, quelque chose comme

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

    ne peut pas être fait

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

Watcher

Un observateur de l'échantillon:

watch: {
   val (n, o) {
     console.log(n, o)
   }
}
  1. Il ne crée pas de nouvelles de la propriété, mais il surveille les changements du réactif.

  2. Montres seulement une propriété spécifique, à la différence calculée où tout dépendant de changement de propriété peut entraîner un nouveau calcul.

  3. A des arguments de la nouvelle et l'ancienne valeur.


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

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

Ou la réduction de longueur variable comme c'est assez commun:

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

peut être réduite à:

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

Non seulement la réduction de taille variable, à chaque fois que le magasin de mises à jour, vous disposez de la dernière valeur en someDeeplyNestedProperty.


Et les Observateurs sont utiles si vous voulez voir si l'un des réactifs de la propriété a changé pour un favorable de la valeur de savoir que vous êtes prêt à effectuer une action.

comme:

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

25voto

Linus Borg Points 9887

Les propriétés calculées ont un but très précis: la composition de nouvelles données provenant d'autres données. Ils sont utilisés chaque fois que vous avez des données et la nécessité de le transformer, de le filtrer, ou autrement manipuler avant de l'utiliser dans le modèle.

Les propriétés calculées toujours retourner une valeur, ne devrait pas avoir d'effets secondaires, et ils doivent être synchrones.

Donc il y a bien des situations où les propriétés calculées ne vous aidera pas, par exemple: votre composant reçoit un accessoire, et à chaque fois que l'hélice changements, votre composant dû faire une requête ajax. Pour cela, vous auriez besoin d'un observateur.

Les observateurs ne sont pas utiles aussi souvent que les propriétés calculées, de sorte que vous devriez toujours penser à si oui ou non une propriété calculée peut résoudre votre problème, et seulement revenir un observateur (ou parfois une méthode) si ce n'est pas le cas.

16voto

Humoyun Points 2120

Vue.js est réactif

Cela signifie qu'il est capable de réagir à des choses comme la saisie de l'utilisateur et les modifications de données. Je vous recommande la lecture sur la réactivité du système pour avoir une meilleure compréhension de la mécanique de Vue est à l'aide de sous le capot quand une modification de données est observée. Il existe trois principales façons d'avoir de vos pièces d'utiliser de Vue de la nature réactive. Ce sont les Méthodes, les Propriétés Calculées et les Observateurs. Sans contrôle, ces options ne semblent interchangeables (et, à certains égards, ils sont), mais chacun d'eux a leur meilleur scénario de cas d'utilisation. Pour aider à illustrer les exemples, je vais faire un petit classement de l'app qui permet à un enseignant d'entrée de test scores pour les étudiants dans leur classe, en vue de la moyenne et de l'ensemble de l'échafaudage pour une fonction d'enregistrement automatique.

MÉTHODES

TL;DR – Utiliser des méthodes lorsque vous souhaitez modifier un composant de l'état ou lorsqu'un événement se produit qui n'est pas nécessairement lié aux données d'instance d'être muté. Les méthodes peuvent prendre des arguments, mais ne pas garder une trace de toutes les dépendances. Lorsque vous utilisez une méthode, il crée habituellement des effets secondaires au sein de la composante et les méthodes sont exécutées chaque fois que le composant est rechargé. Cela signifie que si l'INTERFACE utilisateur est mis à jour très fréquemment, cette méthode (et de toute autre méthode sur le composant) fonctionnera aussi bien. Cela pourrait provoquer des problèmes de performances ou de retard dans l'INTERFACE utilisateur.

Ci-dessous est le début de notre classement de l'app. Il n'y a pas de validation ou quoi que ce soit et son pas assez, je le sais. Nous avons une petite série de tests dans notre objet de données (nom de l'étudiant et score). Et une méthode, nous pouvons l'utiliser pour ajouter un autre objet de test à nos données de propriété "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>

LES PROPRIÉTÉS CALCULÉES

TL;DR – Utilisation d'une propriété calculée lorsque vous souhaitez muter une propriété dépendant d'un autre bien changé. Les propriétés calculées sont généralement tributaires d'autres propriétés des données. Toute modification des propriétés dépendantes de déclencher la logique de la propriété calculée. Les propriétés calculées sont mis en cache en fonction de leur dépendances de sorte qu'ils ne réexécuter si une dépendance changements. (Par exemple, une propriété calculée qui renvoie une nouvelle Date() permet de ne jamais exécuter à nouveau, car la logique ne sera jamais plus que 1 fois) les propriétés Calculées sont les méthodes de lecture par défaut, mais un setter fonction peut être réglée si nécessaire pour obtenir une fonctionnalité similaire.

Dans notre classement de l'app, nous voulons garder une trace de la moyenne de score à un test que nous entrons dans plus de données. Nous allons ajouter une propriété calculée appelé "moyenne" qui sera de retour le score moyen des tests dans notre base de données. La "moyenne" calculée de la propriété sera mis à jour lorsque nous ajoutons un autre test du score.

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>

Les OBSERVATEURS

TL;DR – Utilisation d'observateurs lorsque vous devez effectuer une certaine logique en tant que résultat d'un changement qui a eu lieu sur une propriété de données. Regardé les propriétés de n'agir que sur une seule propriété. Ceci est particulièrement utile lorsque vous souhaitez effectuer asynchrone ou des opérations coûteuses en réponse à l'évolution des données. Gardez à l'esprit les observateurs ne changera que lorsque les données spécifiques des modifications de la propriété.

Laissez-nous faire semblant de l'utilisateur final de notre petit classement de l'app est un professeur de 300 tests de qualité. Qui peut prendre du temps. Une fonction d'enregistrement automatique serait bien d'avoir dans le cas de notre utilisateur final obtient à la fin de la pile de tests et oublie manuellement cliquez sur enregistrer. Dans notre code vous permet d'ajouter un de ceux qui veillent à notre créé précédemment calculée de la propriété "moyen". Quand il est changé (en tant que résultat d'un nouveau score à un test d'ajout et la moyenne des cours de mise à jour) appelons un nouveau "autosave" méthode qui pourrait être utilisée pour appeler une API et sauver notre 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>

3voto

craig_h Points 14240

Vous utilisez un observateur lorsque vous souhaitez muter une valeur ou d'effectuer une action en fonction d'autres la modification de la valeur. Un bon exemple de cela est lorsque vous définissez une valeur basée sur un pilier et vous voulez 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, parce que nous ne sommes pas de la synchronisation des valeurs, donc voici un exemple réel où je me sers de ce dans une de mes projets open source:

Computeds sont arbitrairement pour manipuler les données lui-même, donc les choses comme la concaténation de chaînes et de calcul de valeurs.

2voto

dimlucas Points 3105

Pour les besoins de cet exemple, les propriétés calculées sont en effet mieux. Dans l'exemple qui utilise les observateurs de l'avis 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 but, ils sont en train de regarder pour les changements de nom ou prénom et mise à jour de fullName en conséquence. Mais puisque cela ne changera jamais et fullName sera toujours composé par firstName et lastName alors nous pouvons éviter l'agitation et de créer une propriété calculée. Puis, à chaque fois firstName et lastName changement fullName sera mis à jour automatiquement.

Il y a certains cas où l'utilisation d'observateurs est meilleur. Lorsque vous voulez faire un peu de sérieux calcul d'écrire du code asynchrone puis un observateur pourrait être plus approprié.

Par exemple, si vous aviez quelque chose comme ce qui suit:

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

Et vous voulez, à chaque fois qu' name changements, pour faire un appel d'API avec elle, obtenir le résultat et le processus, alors un observateur est plus approprié:

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

De le faire avec une propriété calculée pour la mise en œuvre d'un computed get() et computed set() de la propriété qui entraînerait plus de code.

Notez également que dans la documentation de l'exemple, nous avons une propriété, fullName qui est composé d'une.k.un calculées par les deux autres propriétés. Dans mon exemple, name n'est pas calculé, dans le sens littéral du terme. Nous voulons juste de l'observer, donc à l'aide d'une propriété calculée serait plus un hack au lieu d'un modèle de conception.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X