Existe-t-il un moyen approprié de réinitialiser les données initiales d'un composant dans vuejs?

92

J'ai un composant avec un ensemble spécifique de données de départ:

data: function (){
    return {
        modalBodyDisplay: 'getUserInput', // possible values: 'getUserInput', 'confirmGeocodedValue'
        submitButtonText: 'Lookup', // possible values 'Lookup', 'Yes'
        addressToConfirm: null,
        bestViewedByTheseBounds: null,
        location:{
            name: null,
            address: null,
            position: null
        }
}

Ce sont des données pour une fenêtre modale, donc quand elle s'affiche, je veux qu'elle commence avec ces données. Si l'utilisateur annule à partir de la fenêtre, je souhaite réinitialiser toutes les données.

Je sais que je peux créer une méthode pour réinitialiser les données et réinitialiser manuellement toutes les propriétés des données à leur origine:

reset: function (){
    this.modalBodyDisplay = 'getUserInput';
    this.submitButtonText = 'Lookup';
    this.addressToConfirm = null;
    this.bestViewedByTheseBounds = null;
    this.location = {
        name: null,
        address: null,
        position: null
    };
}

Mais cela semble vraiment bâclé. Cela signifie que si jamais je modifie les propriétés de données du composant, je devrai m'assurer de ne pas oublier de mettre à jour la structure de la méthode de réinitialisation. Ce n'est pas absolument horrible puisqu'il s'agit d'un petit composant modulaire, mais cela fait hurler la partie optimisation de mon cerveau.

La solution qui, selon moi, fonctionnerait serait de récupérer les propriétés de données initiales dans une readyméthode, puis d'utiliser ces données enregistrées pour réinitialiser les composants:

data: function (){
    return {
        modalBodyDisplay: 'getUserInput', 
        submitButtonText: 'Lookup', 
        addressToConfirm: null,
        bestViewedByTheseBounds: null,
        location:{
            name: null,
            address: null,
            position: null
        },
        // new property for holding the initial component configuration
        initialDataConfiguration: null
    }
},
ready: function (){
    // grabbing this here so that we can reset the data when we close the window.
    this.initialDataConfiguration = this.$data;
},
methods:{
    resetWindow: function (){
        // set the data for the component back to the original configuration
        this.$data = this.initialDataConfiguration;
    }
}

Mais l' initialDataConfigurationobjet change avec les données (ce qui est logique car dans la méthode de lecture, nous initialDataConfigurationobtenons la portée de la fonction de données.

Existe-t-il un moyen de récupérer les données de configuration initiales sans hériter de la portée?

Est-ce que je réfléchis trop à cela et qu'il existe un moyen meilleur / plus simple de le faire?

Le codage en dur des données initiales est-il la seule option?

Chris Schmitz
la source
Utilisez-vous v-show ou v-if pour afficher le modal?
Rwd
J'utilise bootstrap pour le css, donc j'utilise son modal intégré qui exploite jquery pour l'affichage et le masquage. Donc, essentiellement, la partie fenêtre du composant est toujours là, juste cachée.
Chris Schmitz

Réponses:

125
  1. extraire les données initiales dans une fonction en dehors du composant
  2. utilisez cette fonction pour définir les données initiales dans le composant
  3. réutilisez cette fonction pour réinitialiser l'état si nécessaire.

// outside of the component:
function initialState (){
  return {
    modalBodyDisplay: 'getUserInput', 
    submitButtonText: 'Lookup', 
    addressToConfirm: null,
    bestViewedByTheseBounds: null,
    location:{
      name: null,
      address: null,
      position: null
    }
  }
}

//inside of the component:
data: function (){
    return initialState();
} 


methods:{
    resetWindow: function (){
        Object.assign(this.$data, initialState());
    }
}

Linus Borg
la source
5
Cela l'a fait. Merci! J'ai apporté une petite modification à la réponse, mais uniquement parce qu'un composant vue nécessite une fonction renvoyée pour les données au lieu d'un simple objet. Votre concept de réponses fonctionne et est correct, la modification est juste pour rendre compte de la façon dont vuejs gère les composants.
Chris Schmitz
3
Vous avez raison au sujet de la fonction de la propriété de données, c'était moi qui était bâclé. Merci pour la modification.
Linus Borg
13
Il donne maintenant une erreur:[Vue warn]: Avoid replacing instance root $data. Use nested data properties instead.
Sankalp Singha
34
@SankalpSingha Vue 2.0 ne vous permet plus de faire cela. Vous pouvez utiliser à la Object.assignplace. Voici le code de travail: codepen.io/CodinCat/pen/ameraP?editors=1010
CodinCat
3
Pour ce problème - [Vue warn]: évitez de remplacer la racine de l'instance $ data. Utilisez plutôt les propriétés de données imbriquées, essayez ceci: $ data.propName = "new value";
Stanislav Ostapenko
32

Pour réinitialiser un composant datadans une instance de composant actuelle, vous pouvez essayer ceci:

Object.assign(this.$data, this.$options.data())

En privé, j'ai un composant modal abstrait qui utilise des emplacements pour remplir diverses parties du dialogue. Lorsque le modal personnalisé encapsule ce modal abstrait, les données référencées dans les emplacements appartiennent à la portée du composant parent . Voici une option du modal abstrait qui réinitialise les données à chaque fois que le modal personnalisé est affiché (code ES2015):

watch: {
    show (value) { // this is prop's watch
      if(value) {
        Object.assign(this.$parent.$data, this.$parent.$options.data())
      }
    }
}

Vous pouvez bien sûr affiner votre implémentation modale - ci-dessus peut également être exécuté dans un cancelhook.

Gardez à l'esprit que la mutation des $parentoptions de child n'est pas recommandée, mais je pense que cela peut être justifié si le composant parent personnalise simplement le modal abstrait et rien de plus.

Gertas
la source
1
Cette technique donne maintenant un avertissement VueJS; voir stackoverflow.com/questions/40340561/…
Kivi Shapiro
7
Attention, cela ne lie pas le contexte data. Donc, si vous utilisez thisdans votre dataméthode, vous pouvez appliquer le contexte avec:Object.assign(this.$data, this.$options.data.apply(this))
Si ce n'est pas le
Quel est l'avantage de ces méthodes par rapport à location.reload ()?
Carlos le
29

Attention, Object.assign(this.$data, this.$options.data())ne lie pas le contexte dans data ().

Alors utilisez ceci:

Object.assign(this.$data, this.$options.data.apply(this))

cc cette réponse était à l'origine ici

roli roli
la source
3

Si vous êtes ennuyé par les avertissements, voici une méthode différente:

const initialData = () => ({})

export default {
  data() {
    return initialData();
  },
  methods: {
    resetData(){
      const data = initialData()
      Object.keys(data).forEach(k => this[k] = data[k])
    }
  }
}

Pas besoin de jouer avec $ data.

srmico
la source
2

J'ai dû réinitialiser les données à leur état d'origine à l'intérieur d'un composant enfant, c'est ce qui a fonctionné pour moi:

Composant parent, appelant la méthode du composant enfant:

     <button @click="$refs.childComponent.clearAllData()">Clear All</button >

     <child-component ref='childComponent></child-component>

Composant enfant:

  1. définir des données dans une fonction extérieure,
  2. affectation de l'objet de données à une fonction extérieure
  3. définition de la méthode clearallData () qui doit être appelée par le composant parent

    function initialState() {
       return { 
         someDataParameters : '',
         someMoreDataParameters: ''
              }
      }
    
    export default {
       data() {
        return initialState();
      },
        methods: {
      clearAllData() {
      Object.assign(this.$data, initialState());
    },
    
Armin
la source