web-dev-qa-db-fra.com

Comment puis-je changer la valeur des données d'un composant à un autre composant dans Vue Js?

Je suis nouveau dans Vue Js. Donc, je suis confronté à un problème pour changer la valeur des données d'un autre composant.

J'ai un composant A:

<template>
   <div id="app">
      <p v-on:click="test ()">Something</p>
   </div>
</template>

import B from '../components/B.vue';
export default {
    components: {
        B
    },
    methods: {
        test: function() {
            B.data().myData = 124
            B.data().isActive = true
            console.log(B.data().myData);
            console.log(B.data().isActive);
        }
    }
}

Composant B:

export default {
    data() {
        return {
            myData: 123,
            isActive: false

        }
    }

}

Il contient toujours des données B. Mais il ne peut pas être affecté les données du composant B. Je souhaite enregistrer les modifications du composant B par rapport au composant A. Comment faire?

Veuillez m'expliquer en détail. J'ai vu vue js props attribute mais je ne comprends pas.

10
Sukanta Bala

Vous recherchez Vuex .

C'est le magasin centralisé de toutes les données de vos applications.

Jetez un oeil à leur documentation, elle devrait être assez simple.

5
mutantkeyboard

Vous pouvez transmettre des accessoires au composant B. Ces accessoires peuvent être mis à jour par le composant parent. Vous pouvez considérer B comme un composant stupide qui rend juste ce que le parent lui dit de rendre. Exemple:

// Component A
<template>
   <div id="app">
      <p v-on:click="test ()">Something</p>
      <b data="myData" isActive="myIsActive"></b>
   </div>
</template>

<script>
import B from '../components/B.vue';
export default {
  components: {
    B
  },
  data() {
    return {
      myData: 0,
      myIsActive: false,
    };
  },
  methods: {
    test: function() {
      this.myData = 123
      this.myIsActive = true
    }
  }
}
</script>

// Component B
<template>
  <div>{{ data }}{{ isActive }}</div>
</template>

<script>
export default {
  props: {
    data: Number,
    isActive: Boolean
};
</script>
3
truefalse10

Il y a peu de façons ...

  1. si vos composants ont une relation parent-enfant, vous pouvez transmettre des valeurs de données du parent à l'enfant.

  2. Si vous souhaitez communiquer à nouveau avec le composant parent lorsque le composant enfant a changé quelque chose, vous pouvez utiliser l'émetteur d'événement vuejs (événement personnalisé) pour émettre un événement lorsque la valeur des données change et que cet événement peut être écouté dans un autre composant et faire ce que vous voulez.

  3. Si vos composants n'ont pas de relation, vous devez utiliser autre chose que les éléments ci-dessus. Vous pouvez utiliser deux choses: l'une est un bus d'événements, l'autre est une bibliothèque de gestion d'état. Pour vue il existe une bibliothèque officielle de gestion d'état appelée VueX.it est très facile à utiliser. Si vous voulez utiliser autre chose que vuex, vous pouvez l'utiliser comme redux, mobx etc.

Cette documentation contient tout ce que vous voulez savoir. Je ne veux pas mettre de code, car la doc est très claire.

VueX est le moyen le plus préférable de le faire! Très simple d'utilisation ..

https://vuejs.org/v2/guide/components.html

//component A
Vue.component('my-button', {
  props: ['title'],
  template: `<button v-on:click="$emit('add-value')">{{title}}</button>`
});


Vue.component('my-viewer', {
  props: ['counter'],
  template: `<button>{{counter}}</button>`
});

new Vue({
  el: '#app',
  data: {
    counter: 0,
  },
  methods: {
    doSomething: function() {
      this.counter++;
    }
  }
})


Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
});

//parent
new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [{
        id: 1,
        title: 'My journey with Vue'
      },
      {
        id: 2,
        title: 'Blogging with Vue'
      },
      {
        id: 3,
        title: 'Why Vue is so fun'
      }
    ]
  }
});


Vue.component('blog-post2', {
  props: ['post'],
  template: `
                  <div class="blog-post">
                     <h3>{{ post.title }}</h3>
                     <button v-on:click="$emit('enlarge-text')">
                         Enlarge text
                     </button>
                     <div v-html="post.content"></div>
                 </div>`
})

new Vue({
  el: '#blog-posts-events-demo',
  data: {
    posts: [{
        id: 1,
        title: 'My journey with Vue'
      },
      {
        id: 2,
        title: 'Blogging with Vue'
      },
      {
        id: 3,
        title: 'Why Vue is so fun'
      }
    ],
    postFontSize: 1
  },
  methods: {
    onEnlargeText: function() {
      this.postFontSize++;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<p>Two components adding & viewing value</p>
<div id="app">
  <my-button :title="'Add Value'" v-on:add-value="doSomething"></my-button>
  <my-viewer :counter="counter"></my-viewer>
</div>
<br>
<br>
<p>Passing Data to Child Components with Props (Parent to Child)</p>
<div id="blog-post-demo">
  <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title"></blog-post>
</div>

<p>Listening to Child Components Events (Child to Parent)</p>
<div id="blog-posts-events-demo">
  <div :style="{ fontSize: postFontSize + 'em' }">
    <blog-post2 v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-on:enlarge-text="onEnlargeText"></blog-post2>
  </div>
</div>

Tout d'abord, vous avez besoin d'un parent pour que deux composants puissent communiquer. lorsque l'on clique sur le composant my-button déclenche un événement add-value qui appelle la fonction doSomething(), puis met à jour la valeur et l'affiche au composant my-viewer.

[~ # ~] html [~ # ~]

     <!--PARENT-->
     <div id="app"> 
          <!--CHILD COMPONENTS-->
          <my-button :title="'Add Value'" v-on:add-value="doSomething"></my-button>
          <my-viewer :counter="counter"></my-viewer>
     </div>

VUE.JS

     //component A
     Vue.component('my-button',{
         props:['title'],
         template:`<button v-on:click="$emit('add-value')">{{title}}</button>`
     });

     //Component B
     Vue.component('my-viewer',{
        props:['counter'],
        template:`<button>{{counter}}</button>`
     });

     //Parent
     new Vue({
         el: '#app',
         data:{
            counter:0,
         },
         methods:{
             doSomething:function(){
               this.counter++;
             }
        }
     })

Ceci est basé sur Guide des composants Vue

Passage de données aux composants enfants avec des accessoires (parent à enfant)

VUE.JS

         //component (child)
         //Vue component must come first, else it won't work
         Vue.component('blog-post', {
             /*Props are custom attributes you can register on a component. When a 
               value is passed to a prop attribute, it becomes a property on that 
               component instance*/
             props: ['title'],
             template: '<h3>{{ title }}</h3>'
         });

         //parent
         new Vue({
            el: '#blog-post-demo',
            data: {
              posts: [
                 { id: 1, title: 'My journey with Vue' },
                 { id: 2, title: 'Blogging with Vue' },
                 { id: 3, title: 'Why Vue is so fun' }
              ]
            }
         });

HTML:

v-for Bouclera sur les publications et transmettra les données au composant blog-post

         <div id="blog-post-demo">
             <blog-post  v-for="post in posts"
                         v-bind:key="post.id"
                         v-bind:title="post.title"></blog-post>
         </div>

Écoute des événements des composants enfants (enfant à parent)

[~ # ~] html [~ # ~]

Vous devez d'abord enregistrer l'événement par v-on:enlarge-text="onEnlargeText" Pour utiliser $emit Et vous assurer qu'il est toujours réglé en minuscules ou il ne fonctionnera pas correctement. exemple enlargeText et Enlargetext seront toujours convertis en enlargetext, utilisez donc agrandir-texte à la place, car il est facile à lire et valide, pour une brève explication sur $emit vous pouvez le lire ici

         <div id="blog-posts-events-demo">
            <div :style="{ fontSize: postFontSize + 'em' }">
                 <blog-post
                          v-for="post in posts"
                          v-bind:key="post.id"
                          v-bind:post="post"
                          v-on:enlarge-text="onEnlargeText"></blog-post>
            </div>
         </div>

VUE.JS

Lorsque l'utilisateur clique sur button, la v-on:click="$emit('enlarge-text')" se déclenche, puis appelle la fonction onEnlargeText() dans le parent

         //component (child)
         Vue.component('blog-post', {
             props: ['post'],
             template: `
              <div class="blog-post">
                 <h3>{{ post.title }}</h3>
                 <button v-on:click="$emit('enlarge-text')">
                     Enlarge text
                 </button>
                 <div v-html="post.content"></div>
             </div>`
         })

         //parent
         new Vue({
            el: '#blog-posts-events-demo',
            data: {
               posts: [
                    { id: 1, title: 'My journey with Vue' },
                    { id: 2, title: 'Blogging with Vue' },
                    { id: 3, title: 'Why Vue is so fun' }
               ],
            postFontSize: 1
         },
         methods:{
            onEnlargeText:function(){
               this.postFontSize++;
            }
          }
        })
0
NJY404