3 votes

Vue.js2 - Méthode de surveillance préventive Object.assign({}, this.var)

Le renvoi de this.user (une propriété globale calculée) fonctionne comme prévu. Bien sûr, je fais une copie car je ne veux pas écraser les données réelles de l'utilisateur. J'utilise donc Object.assign. Cependant, dès que j'inclus return Object.assign({}, this.user) (par opposition à this.user), la méthode watch ne fonctionne plus.

Voici mon modèle (j'utilise bootstrap-vue) :

<template>
  <form role="form">
    <b-form-group
      label="First Name"
      label-for="basicName"
      :label-cols="3"
      :horizontal="true">
        <b-form-input id="user-name-first" type="text" v-model="userFormData.fname"></b-form-input>
    </b-form-group>
          <b-form-group
      label="Last Name"
      label-for="basicName"
      :label-cols="3"
      :horizontal="true">
        <b-form-input id="user-name-lirst" type="text" v-model="userFormData.lname"></b-form-input>
    </b-form-group>
          <b-form-group
      label="Email"
      label-for="user-email"
      :label-cols="3"
      :horizontal="true">
        <b-form-input id="user-email" type="text" v-model="userFormData.email"></b-form-input>
    </b-form-group>
      <b-form-group
          :label-cols="3"
          :horizontal="true">
                    <b-button type="submit" variant="primary">Save changes</b-button>
            <b-button type="button" variant="secondary" @click="userFormCancel">Cancel</b-button>
        </b-form-group>
      </form>
</template>

Donc, cela fonctionne et met éditsEn attente à vrai à chaque fois que des changements sont appliqués à Profil de l'utilisateur (via v-model sur une entrée)

<script>
export default {
  name: 'userProfile',
  data () {
    return {
      editsPending: false
    }
  },
  computed: {
    userFormData: function () {
      return this.user
    }
  },
  watch: {
    userFormData: {
      deep: true,
      handler (val) {
        this.editsPending = true
      }
    }
  },
  methods: {
    userFormCancel () {
      this.editsPending = false
    }
  }
}
</script>

...mais ce n'est pas le cas ; userFormData devient un clone de utilisateur pero éditsEn attente n'est pas affecté par les mises à jour de userFormData .

<script>
export default {
  name: 'userProfile',
  data () {
    return {
      editsPending: false
    }
  },
  computed: {
    userFormData: function () {
      return Object.assign({}, this.user)
    }
  },
  watch: {
    userFormData: {
      deep: true,
      handler (val) {
        this.editsPending = true
      }
    }
  },
  methods: {
    userFormCancel () {
      this.editsPending = false
    }
  }
}
</script>

Quelqu'un peut-il expliquer pourquoi cela se produit et proposer une solution viable ?

1voto

Sovalina Points 4185

Une propriété calculée ne sera réévaluée que lorsque certaines de ses propriétés dépendances ont changé. ( source )

C'est pourquoi il fonctionne avec return this.user et non avec Object.assign car il ne s'agit pas d'une dépendance réactive.

Si vous voulez des données réactives, vous devez initialiser userFormData comme un objet vide de données et assignez votre utilisateur lorsque votre instance Vue est créée :

  data () {
    return {
      editsPending: false,
      userFormData: {}
    }
  },
  created() {
    this.userFormData = Object.assign({}, this.user)
  },

0voto

J'ai testé différentes choses pour reproduire le comportement que vous voyez.

Je soupçonne que dans votre modèle vous liez vos entrées à UserFormdata (incorrect)

<input v-model="userFormData.name">

Au lieu de (correct)

<input v-model="user.name">

Si vous pouviez partager votre modèle, cela nous aiderait ;)

Edit : Après l'ajout du modèle.

new Vue({
  el: '#app',
  data () {
    return {
      editsPending: false,
      user: { name: 'John Doe' },
      userCachedData: {},
    }
  },
  created() {
    this.userCachedData = Object.assign({}, this.user);
  },
  watch: {
    user: {
      deep: true,
      handler (val) {
        this.editsPending = true
      }
    }
  },
  methods: {
    userFormCancel () {
      this.editsPending = false
    }
  }
})

<div id="app">
  {{ user }}
  {{ userCachedData }}
  <br>
  <input v-model="user.name" />
  {{ this.editsPending }}
</div>

Codepen : https://codepen.io/aurelien-bottazini/pen/BVNJaG?editors=1010

0voto

Darlan Dieterich Points 168

Vous pouvez utiliser le $emit pour attribuer une valeur à l'objet :

mounted() {
  this.$emit("userFormData", this.user);
}

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