web-dev-qa-db-fra.com

Évitez de muter directement un accessoire, car la valeur sera écrasée

J'ai un problème très commun avec la mise à niveau vers Vue 2.0 

Je reçois un avertissement: 

Évitez de muter directement un accessoire car la valeur sera écrasée chaque fois que le composant parent est rendu. Au lieu de cela, utilisez une donnée ou propriété calculée en fonction de la valeur de l'accessoire. Prop étant muté: "nom d'utilisateur" (trouvé dans le composant)

J'ai lu la documentation plusieurs fois mais je ne comprends toujours pas comment le corriger.

username et password sont déclarés dans l'application Vue principale. 

Voici mon code:

var GuestMenu = Vue.extend({
   props : ['username', 'password'],
      template: `
        <div id="auth">
            <form class="form-inline pull-right">
                <div class="form-group">
                    <label class="sr-only" for="UserName">User name</label>
                  <input type="username" v-model="username" class="form-control" id="UserName" placeholder="username">
                </div>
                <div class="form-group">
                  <label class="sr-only" for="Password">Password</label>
                  <input type="password" v-model="password" class="form-control" id="Password" placeholder="Password">
                </div>
            </form>
        </div>`,
    });

App = new Vue ({ 
   el: '#app',
  data: 
    {
      topMenuView: "guestmenu",
      contentView: "guestcontent",
      username: "",
      password: "",

    }
})

J'ai essayé v-bind mais cela ne semble pas fonctionner et je ne comprends pas pourquoi. Il devrait lier la valeur au parent (l’application Vue principale)

13
Dmitry Bubnenkov

Depuis Vue 2.3.0, vous pouvez utiliser le modificateur .sync:

Exemple vom https://vuejs.org/v2/guide/components-custom-events.html#sync-Modifier :

<text-document :title.sync="title"></text-document>

et dans votre contrôleur ...

this.$emit('update:title', newTitle)
8
Gerfried

Vue.js considère cela comme un anti-motif. Par exemple, en déclarant et en définissant des accessoires comme

this.propsVal = 'new Props Value'

Donc, pour résoudre ce problème, vous devez prendre la valeur des accessoires aux données ou à la propriété calculée de l’instance Vue. comme... 

props: ['propsVal'],
data: function() {
   return {
       propVal: this.propsVal
   };
},
methods: {
...
}

et vous pouvez utiliser votre valeur d'accessoire comme d'habitude.

7
iamsangeeth

Vous devez créer une propriété calculée avec un getter et un setter, puis utiliser $emit pour mettre à jour la propriété, par exemple:

var GuestMenu = Vue.extend({
    props: ['username', 'password'],
    template: `
    <div id="auth">
        <form class="form-inline pull-right">
            <div class="form-group">
                <label class="sr-only" for="UserName">User name</label>
              <input type="username" v-model="usernameInput" class="form-control" id="UserName" placeholder="username">
            </div>
            <div class="form-group">
              <label class="sr-only" for="Password">Password</label>
              <input type="password" v-model="passwordInput" class="form-control" id="Password" placeholder="Password">
            </div>
        </form>
    </div>`,
    computed: {
        usernameInput: {
            get: function(){
                return this.username;
            },
            set: function(newValue){
                this.$emit('update:username', newValue)
            }   
        },
        passwordInput: {
            get: function(){
                return this.password;
            },
            set: function(newValue){
                this.$emit('update:password', newValue)
            }   
        },
    }
});
2
Andy

Je ne sais pas exactement ce que vous voulez réaliser, mais je vais prendre deux options.

Premier point: il s'agit de se débarrasser de cet avertissement.

data () {
  return {
    childVal: this.parentVal
  }
}

Deuxième question: vous souhaitez communiquer entre parent et enfant.

Si j'ai bien compris, il s'agit d'un exemple de base d'un <input> dans un composant enfant communiquant avec son parent.

HTML parent:

<p>{{ user }}</p>
<child-component v-model="user">

Parent JS:

data () {
  return {
    user: 'John'
  }
}

HTML enfant:

<input v-bind:value="value" @input="$emit('input', $event.target.value)">

Enfant JS:

props: ['value']

Exemple de travail: http://jsfiddle.net/kf3aLr1u/

Vous pouvez également en savoir plus à ce sujet dans docs https://vuejs.org/v2/guide/components.html .

1
Lucas G.

Une propriété computed avec les get et set appropriés a fonctionné pour moi: 

computed: {
  dialogDataProp: {
      get: function() {
        return this.dialog;
      },
      set: function() {}
    }
}

Code ci-dessus pour basculer une boîte de dialogue.

1
CodeFinity

si vous voulez muter les accessoires - utilisez object.

<component :user="global.user"></component>

composant:

    props: ['user'],
    methods: {
      setUser: function() {
        this.user.username= "User";
        this.user.password= "myPass123";
      }
    }
0
Aiwass 418

Lorsque vous utilisez v-bind la propriété est liée en utilisant deux directions, c'est pourquoi vous obtenez l'avertissement.

Si vous devez transmettre le nom d'utilisateur initial du composant Vue parent, vous pouvez utiliser v-bind avec une autre propriété de données telle que _username et copier la valeur initiale de la propriété dans les données internes lors de la création du composant: 

props : ['username', 'password'],
data () {
  return {
    _username: this.username,
    _password: this.password
  }
}

Edit: vous pouvez également utiliser une surveillance $ pour mettre à jour les données du composant _username/_password lorsque les propriétés changent.

0
TiagoLr