Transmission de données aux composants dans vue.js

J'ai du mal à comprendre comment transmettre des données entre les composants dans vue.js. J'ai lu les documents plusieurs fois et regardé de nombreuses questions et tutoriels liés à vue, mais je ne l'obtiens toujours pas.

Pour envelopper ma tête autour de cela, j'espère de l'aide pour compléter un exemple assez simple

  1. affiche une liste d'utilisateurs dans un composant (terminé)
  2. envoie les données utilisateur à un nouveau composant lorsqu'un lien est cliqué (terminé) - voir Mise à jour à bas.
  3. modifiez les données utilisateur et renvoyez-les au composant d'origine (je n'ai pas été aussi loin)

Voici un violon, qui échoue à l'étape deux: https://jsfiddle.net/retrogradeMT/d1a8hps0/

Je comprends que j'ai besoin d'utiliser des accessoires pour transmettre des données au nouveau composant, mais je ne suis pas sûr de savoir 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 le 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,
        }
   },
})

Mise à JOUR

Ok, j'ai compris la deuxième étape. 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.

V-link change voir les routes nommées dans les documents vue-router :

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

Ensuite, sur le composant, ajoutez données vers les options d'itinéraire 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,
        }
   },
})
57
demandé sur retrograde 2015-12-30 20:24:55

5 réponses

-------------ci-dessous est applicable uniquement à Vue 1 --------------

La transmission de données peut se faire de plusieurs façons. 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 en utilisant des accessoires.

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

Cette valeur prop ne sera disponible pour votre composant que si vous ajoutez le nom 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 ceci:

<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> alors dans <my-child-A> vous devrez envoyer un événement:

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

Cet événement se déroulera tout le long de la chaîne parente. Et à partir de n'importe quel parent 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 va voyager dans la chaîne des enfants. Et à n'importe quel enfant que vous voulez saisir l'événement, 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 de passer par des paramètres dans des liens V. Cette méthode est utilisée lorsque les chaînes de composants sont complètement détruites ou dans les cas où l'URI change. Et je vois que vous les comprenez déjà.


Décidez quel type de communication de données vous voulez et choisissez de manière appropriée.

30
répondu notANerdDev 2018-08-08 11:55:59

, 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, pas d'une chaîne. Donc, vous n'avez pas besoin du {{}} autour de user.name. Essayez:

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

Modifier - - - - -

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

10
répondu Jeff 2015-12-30 17:54:25

La meilleure façon d'envoyer des données d'un composant parent à un enfant est d'utiliser props .

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

  • déclare props (Tableau ou objet ) dans l'enfant
  • Transmettre à 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/vue@2.5.13/dist/vue.min.js"></script>

<div id="app">
  <p>At Parent: {{ variableAtParent }}</p>
  <child-comp :message="variableAtParent"></child-comp>
</div>
6
répondu acdcjunior 2018-03-05 00:07:54

J'ai trouvé un moyen de transmettre les données parentes à la portée du composant dans Vue, je pense que c'est un peu un hack mais peut-être que cela vous aidera.

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

2) Ensuite, dans la fonction de retour de données dans le composant enfant, retournez simplement parentScope = dataObj et voila. Maintenant, vous ne pouvez pas faire des choses comme {{ parentScope.prop }} et fonctionnera comme un charme.

Bonne Chance!

2
répondu Lucas Serena 2018-08-07 08:46:58

Une variable js globale (objet) peut être utilisée pour passer des données entre les composants. Exemple: transmission de données depuis Ammlogin.vue sur Options.vue. Dans Ammlogin.vue rspData est défini sur la réponse du serveur. Dans Les Options.vue la réponse du serveur est 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>
1
répondu Kjelle J 2018-04-16 16:34:28