116 votes

Quelle est la bonne façon de passer des accessoires comme des données initiales dans Vue.js 2?

Si je veux passer des accessoires pour une Vue de composant, mais j'espère que ces accessoires à changer dans le futur à partir de l'intérieur de ce composant par exemple, quand je l'ai mise à jour de Vue de la composante de l'intérieur à l'aide d'AJAX. Donc, ils ne sont pour l'initialisation du composant.

Mon cars-list Vue composante où je passe des accessoires avec des propriétés initiales à l' single-car:

// cars-list.vue

<script>
    export default {
        data: function() {
            return {
                cars: [
                    {
                        color: 'red',
                        maxSpeed: 200,
                    },
                    {
                        color: 'blue',
                        maxSpeed: 195,
                    },
                ]
            }
        },
    }
</script>

<template>
    <div>
        <template v-for="car in cars">
            <single-car :initial-properties="car"></single-car>
        </template>
    </div>
</template>

La façon dont je le faire dès maintenant que l'intérieur de mon single-car composant je suis attribution d' this.initialProperties mon this.data.properties sur created() initialisation de crochet. Et elle fonctionne et est réactif.

// single-car.vue

<script>
    export default {
        data: function() {
            return {
                properties: {},
            }
        },
        created: function(){
            this.data.properties = this.initialProperties;
        },
    }
</script>

<template>
    <div>Car is in {{properties.color}} and has a max speed of {{properties.maxSpeed}}</div>
</template>

Mais mon problème est que je ne sais pas si c'est une bonne façon de le faire? N'est-ce pas me causer quelques problèmes le long de la route? Ou est-il une meilleure façon de le faire?

127voto

Dominik Serafin Points 86

Grâce à cette https://github.com/vuejs/vuejs.org/pull/567 je sais que la réponse maintenant.

Méthode 1

Initiale prop directement aux données. Comme l'exemple de la mise à jour de documents:

props: ['initialCounter'],
data: function () {
    return {
        counter: this.initialCounter
    }
}

Mais avoir à l'esprit si l'hélice est un objet ou un tableau qui est utilisé dans le composant parent état de toute modification qui prop entraînera le changement de composant parent de l'état.

Avertissement: cette méthode n'est pas recommandée. Il fera de votre composants imprévisible. Si vous avez besoin de ensemble de données parent de l'enfant composants soit utiliser la gestion de l'état comme Vuex ou "v-modèle". https://vuejs.org/v2/guide/components.html#Using-v-model-on-Components

Méthode 2

Si votre première prop est un objet ou un tableau et si vous ne voulez pas que les changements dans les enfants de l'état se propager à l'état parent alors juste utiliser, par exemple, Vue.util.extend [1] de faire une copie des accessoires à la place de la pointer directement aux enfants des données, comme ceci:

props: ['initialCounter'],
data: function () {
    return {
        counter: Vue.util.extend({}, this.initialCounter)
    }
}

Méthode 3

Vous pouvez également utiliser la propagation de l'opérateur de cloner les accessoires. Plus de détails dans le Igor réponse: https://stackoverflow.com/a/51911118/3143704

Mais avoir à l'esprit que la propagation des opérateurs ne sont pas pris en charge dans les navigateurs plus anciens et pour une meilleure compatibilité, vous aurez besoin de transpile le code en utilisant par exemple babel.

Notes de bas de page

[1] d'Avoir à l'esprit que c'est un interne de Vue utilitaire et il peut changer avec les nouvelles versions. Vous pouvez utiliser d'autres méthodes pour copier prop, consultez la section "Comment puis-je correctement cloner un objet JavaScript?".

Mon violon où j'ai été le tester: https://jsfiddle.net/sm4kx7p9/3/

36voto

Igor Parra Points 3858

En compagnon de @dominik-serafin réponse:

Dans le cas où vous êtes de passage à un opbject, vous pouvez cloner facilement à l'aide de la propagation de l'opérateur (ES6):

 props: {
   record: {
     type: Object,
     required: true
   }
 },

data () { // opt. 1
  return {
    recordLocal: {...this.record}
  }
},

computed: { // opt. 2
  recordLocal () {
    return {...this.record}
  }
},

Mais le plus important est de se rappeler d'utiliser l'opt. 2 dans le cas où vous êtes de passage à une valeur calculée, ou plus que cela asynchrone valeur. Sinon, la valeur locale ne sera pas mise à jour.

Démo:

Vue.component('card', { 
  template: '#app2',
  props: {
    test1: null,
    test2: null
  },
  data () { // opt. 1
    return {
      test1AsData: {...this.test1}
    }
  },
  computed: { // opt. 2
    test2AsComputed () {
      return {...this.test2}
    }
  }
})

new Vue({
  el: "#app1",
  data () {
    return {
      test1: {1: 'will not update'},
      test2: {2: 'will update after 1 second'}
    }
  },
  mounted () {
    setTimeout(() => {
      this.test1 = {1: 'updated!'}
      this.test2 = {2: 'updated!'}
    }, 1000)
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

<div id="app1">
  <card :test1="test1" :test2="test2"></card>
</div>

<template id="app2">
  <div>
    test1 as data: {{test1AsData}}
    <hr />
    test2 as computed: {{test2AsComputed}}
  </div>
</template>

https://jsfiddle.net/nomikos3/eywraw8t/281070/

15voto

jonan.pineda Points 834

Je crois que vous êtes en train de faire parce que c'est ce qui est indiqué dans les docs.

Définir une propriété de données qui utilise la prop initiale de valeur que sa valeur initiale

https://vuejs.org/guide/components.html#One-Way-Data-Flow

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