web-dev-qa-db-fra.com

Passing data to components in vue.js

J'ai du mal à comprendre comment transmettre des données entre composants dans vue.js. J'ai lu plusieurs fois la documentation et consulté de nombreuses questions et tutoriels liés à vue, mais je ne comprends toujours pas.

En résumé, j’espère avoir de l’aide pour compléter un exemple assez simple.

  1. afficher une liste d'utilisateurs dans un composant (terminé)
  2. envoyer les données utilisateur à un nouveau composant quand un lien est cliqué (terminé) - voir la mise à jour en bas.
  3. modifier les données utilisateur et les renvoyer au composant d'origine (pas encore atteint)

Voici un violon qui échoue à la deuxième étape: https://jsfiddle.net/retrogradeMT/d1a8hps0/

Je comprends que je dois utiliser des accessoires pour transmettre des données au nouveau composant, mais je ne sais pas comment le faire fonctionnellement. Comment lier les données au nouveau composant?

HTML:

    <div id="page-content">
       <router-view></router-view>
     </div>

 <template id="userBlock" >
   <ul>
     <li v-for="user in users">{{user.name}} - <a v-link="{ path: '/new' }"> Show new component</a>
     </li>
   </ul>
 </template>

  <template id="newtemp" :name ="{{user.name}}">
    <form>
      <label>Name: </label><input v-model="name">
      <input type="submit" value="Submit">
    </form>
  </template>

js pour composant principal:

Vue.component('app-page', {
  template: '#userBlock',

  data: function() {
    return{

        users: []
      }
    },

ready: function () {
    this.fetchUsers();
},

methods: {
    fetchUsers: function(){
        var users = [
          {
            id: 1,
            name: 'tom'
          },
          {
            id: 2,
            name: 'brian'
          },
          {
            id: 3,
            name: 'sam'
          },
        ];

        this.$set('users', users);
     }
    }
  })

JS pour le deuxième composant:

Vue.component('newtemp', {
  template: '#newtemp',
  props: 'name',
  data: function() {
    return {
        name: name,
        }
   },
})

UPDATE

Ok, j'ai la deuxième étape calculée. Voici un nouveau violon montrant les progrès: https://jsfiddle.net/retrogradeMT/9pffnmjp/

Parce que j'utilise Vue-router, je n'utilise pas d'accessoires pour envoyer les données à un nouveau composant. Au lieu de cela, j'ai besoin de définir des paramètres sur le v-link, puis d'utiliser un crochet de transition pour l'accepter.

Modifications de la liaison virtuelle voir les routes nommées dans la documentation de vue-router :

<a v-link="{ name: 'new', params: { name: user.name }}"> Show new component</a>

Ensuite, sur le composant, ajoutez des données aux options de route voir crochets de transition :

Vue.component('newtemp', {
  template: '#newtemp',
  route: {
   data: function(transition) {
        transition.next({
            // saving the id which is passed in url
            name: transition.to.params.name
        });
     }
  },
 data: function() {
    return {
        name:name,
        }
   },
})
71
retrograde

------------- Ce qui suit s’applique uniquement à Vue 1 --------------

La transmission de données peut être effectuée de plusieurs manières. La méthode dépend du type d'utilisation.


Si vous souhaitez transmettre des données de votre code HTML pendant que vous ajoutez un nouveau composant. Cela se fait à l'aide d'accessoires.

<my-component prop-name="value"></my-component>

Cette valeur de prop n'est disponible pour votre composant que si vous ajoutez le nom de prop prop-name à votre attribut props.


Lorsque des données sont transmises d'un composant à un autre composant en raison d'un événement dynamique ou statique. Cela se fait en utilisant des répartiteurs d’événements et des diffuseurs. Donc, par exemple, si vous avez une structure de composant comme celle-ci:

<my-parent>
    <my-child-A></my-child-A>
    <my-child-B></my-child-B>
</my-parent>

Et vous voulez envoyer des données de <my-child-A> à <my-child-B>, puis dans <my-child-A>, vous devrez envoyer un événement:

this.$dispatch('event_name', data);

Cet événement voyagera tout au long de la chaîne parente. Et quel que soit le parent sur lequel vous avez une branche vers <my-child-B> vous diffusez l’événement avec les données. Donc dans le parent:

events:{
    'event_name' : function(data){
        this.$broadcast('event_name', data);
    },

Maintenant, cette émission voyagera dans la chaîne enfant. Et quel que soit l'enfant que vous souhaitez saisir, dans notre cas <my-child-B> nous ajouterons un autre événement:

events: {
    'event_name' : function(data){
        // Your code. 
    },
},

La troisième façon de transmettre des données est d'utiliser des paramètres dans v-links. Cette méthode est utilisée lorsque les chaînes de composants sont complètement détruites ou lorsque l'URI change. Et je peux voir que vous les comprenez déjà.


Décidez du type de communication de données que vous souhaitez et choisissez en conséquence.

36
notANerdDev

Le meilleur moyen d'envoyer des données d'un composant parent à un enfant est d'utiliser props .

Passer des données du parent à l'enfant via props

  • Déclarez props (tableau ou objet ) dans l'enfant
  • Transmettez-le à l'enfant via <child :name="variableOnParent">

Voir la démo ci-dessous:

Vue.component('child-comp', {
  props: ['message'], // declare the props
  template: '<p>At child-comp, using props in the template: {{ message }}</p>',
  mounted: function () {
    console.log('The props are also available in JS:', this.message);
  }
})

new Vue({
  el: '#app',
  data: {
    variableAtParent: 'DATA FROM PARENT!'
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

<div id="app">
  <p>At Parent: {{ variableAtParent }}</p>
  <child-comp :message="variableAtParent"></child-comp>
</div>
13
acdcjunior

Je pense que le problème est ici:

<template id="newtemp" :name ="{{user.name}}">

Lorsque vous préfixez l'accessoire avec :, vous indiquez à Vue qu'il s'agit d'une variable et non d'une chaîne. Donc, vous n'avez pas besoin du {{}} autour de user.name. Essayer:

<template id="newtemp" :name ="user.name">

MODIFIER-----

Ce qui précède est vrai, mais le problème majeur est que lorsque vous modifiez l'URL et accédez à un nouvel itinéraire, le composant d'origine disparaît. Pour que le deuxième composant modifie les données parent, le deuxième composant doit être un composant enfant du premier ou juste une partie du même composant.

11
Jeff

J'ai trouvé un moyen de passer des données parent à la portée du composant dans Vue. Je pense que c'est un peu un bidouillage, mais peut-être que cela vous aidera.

1) Données de référence dans Vue Instance en tant qu'objet externe (data : dataObj)

2) Ensuite, dans la fonction de retour des données du composant enfant, il suffit de renvoyer parentScope = dataObj et le tour est joué. Maintenant, vous pouvez faire des choses comme {{ parentScope.prop }} et vous ferez comme un charme.

Bonne chance!

2
Lucas Serena

Une variable JS globale (objet) peut être utilisée pour transmettre des données entre des composants. Exemple: transmission de données d'Ammlogin.vue à Options.vue. Dans Ammlogin.vue, rspData est défini sur la réponse du serveur. Dans Options.vue, la réponse du serveur est rendue disponible via rspData.

index.html:

<script>
    var rspData; // global - transfer data between components
</script>

Ammlogin.vue:

....    
export default {
data: function() {return vueData}, 
methods: {
    login: function(event){
        event.preventDefault(); // otherwise the page is submitted...
        vueData.errortxt = "";
        axios.post('http://vueamm...../actions.php', { action: this.$data.action, user: this.$data.user, password: this.$data.password})
            .then(function (response) {
                vueData.user = '';
                vueData.password = '';
                // activate v-link via JS click...
                // JSON.parse is not needed because it is already an object
                if (response.data.result === "ok") {
                    rspData = response.data; // set global rspData
                    document.getElementById("loginid").click();
                } else {
                    vueData.errortxt = "Felaktig avändare eller lösenord!"
                }
            })
            .catch(function (error) {
                // Wu oh! Something went wrong
                vueData.errortxt = error.message;
            });
    },
....

Options.vue:

<template>
<main-layout>
  <p>Alternativ</p>
  <p>Resultat: {{rspData.result}}</p>
  <p>Meddelande: {{rspData.data}}</p>
  <v-link href='/'>Logga ut</v-link>
</main-layout>
</template>
<script>
 import MainLayout from '../layouts/Main.vue'
 import VLink from '../components/VLink.vue'
 var optData = { rspData: rspData}; // rspData is global
 export default {
   data: function() {return optData},
   components: {
     MainLayout,
     VLink
   }
 }
</script>
0
Kjelle J