Esiste un modo corretto per ripristinare i dati iniziali di un componente in vuejs?


92

Ho un componente con un set specifico di dati di partenza:

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
        }
}

Questi sono dati per una finestra modale, quindi quando viene visualizzato voglio che inizi con questi dati. Se l'utente annulla dalla finestra, voglio ripristinare tutti i dati a questo.

So di poter creare un metodo per ripristinare i dati e ripristinare manualmente tutte le proprietà dei dati al loro originale:

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

Ma questo sembra davvero sciatto. Significa che se mai apporto una modifica alle proprietà dei dati del componente, dovrò assicurarmi di ricordarmi di aggiornare la struttura del metodo di ripristino. Non è assolutamente orribile poiché è un piccolo componente modulare, ma fa urlare la parte di ottimizzazione del mio cervello.

La soluzione che pensavo avrebbe funzionato sarebbe stata quella di afferrare le proprietà dei dati iniziali in un readymetodo e quindi utilizzare i dati salvati per ripristinare i componenti:

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;
    }
}

Ma l' initialDataConfigurationoggetto sta cambiando insieme ai dati (il che ha senso perché nel metodo di lettura il nostro initialDataConfigurationsta ottenendo l'ambito della funzione dati.

C'è un modo per acquisire i dati di configurazione iniziali senza ereditare l'ambito?

Ci sto pensando troppo e c'è un modo migliore / più semplice per farlo?

L'hardcoding dei dati iniziali è l'unica opzione?


Stai usando v-show o v-if per visualizzare il modale?
Rwd

Sto usando bootstrap per il css, quindi lo sto usando in modal che sfrutta jquery per mostrare e nascondere. Quindi essenzialmente la parte della finestra del componente è sempre lì, solo nascosta.
Chris Schmitz

Risposte:


125
  1. estrarre i dati iniziali in una funzione esterna al componente
  2. utilizzare quella funzione per impostare i dati iniziali nel componente
  3. riutilizzare quella funzione per ripristinare lo stato quando necessario.

// 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());
    }
}


5
Quello ha fatto. Grazie! Ho apportato una piccola modifica alla risposta, ma solo perché un componente vue richiede una funzione restituita per i dati anziché solo un oggetto. Il tuo concetto di risposte funziona decisamente ed è corretto, la modifica serve solo per tenere conto di come vuejs gestisce i componenti.
Chris Schmitz

3
Hai ragione riguardo alla funzione per la proprietà data, ero sciatto. Grazie per la modifica.
Linus Borg

13
Ora dà un errore:[Vue warn]: Avoid replacing instance root $data. Use nested data properties instead.
Sankalp Singha

34
@SankalpSingha Vue 2.0 non ti permette più di farlo. Puoi usare Object.assigninvece. Ecco il codice funzionante: codepen.io/CodinCat/pen/ameraP?editors=1010
CodinCat

3
Per questo problema - [Vue warn]: evitare di sostituire i dati $ root dell'istanza. Usa invece le proprietà dei dati nidificati, prova questo. $ Data.propName = "nuovo valore";
Stanislav Ostapenko

32

Per ripristinare il componente datain un'istanza del componente corrente puoi provare questo:

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

In privato ho un componente modale astratto che utilizza gli slot per riempire varie parti della finestra di dialogo. Quando i wrapping modali personalizzati che astraggono il modale, i dati indicati negli slot appartengono all'ambito del componente padre . Ecco l'opzione del modale astratto che ripristina i dati ogni volta che viene mostrato il modale personalizzato (codice ES2015):

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

Ovviamente puoi mettere a punto la tua implementazione modale - sopra può anche essere eseguito in qualche cancelhook.

Tieni presente che la mutazione delle $parentopzioni da bambino non è raccomandata, tuttavia penso che possa essere giustificata se il componente genitore sta solo personalizzando il modale astratto e nient'altro.


1
Questa tecnica ora fornisce un avviso VueJS; vedi stackoverflow.com/questions/40340561/…
Kivi Shapiro

7
Attenzione, questo non vincola il contesto data. Quindi, se stai usando thisnel tuo datametodo, puoi applicare il contesto con:Object.assign(this.$data, this.$options.data.apply(this))
Ifnot

Qual è il vantaggio di questo metodo rispetto a location.reload ()?
Carlos

29

Attenzione, Object.assign(this.$data, this.$options.data())non lega il contesto a data ().

Quindi usa questo:

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

cc questa risposta era originariamente qui


3

Se sei infastidito dagli avvisi, questo è un metodo diverso:

const initialData = () => ({})

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

Non c'è bisogno di scherzare con $ data.


2

Ho dovuto ripristinare i dati allo stato originale all'interno di un componente figlio, questo è ciò che ha funzionato per me:

Componente padre, chiamando il metodo del componente figlio:

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

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

Componente figlio:

  1. definire i dati in una funzione esterna,
  2. assegnazione dell'oggetto dati alla e all'esterno della funzione
  3. definire il metodo clearallData () che deve essere richiamato dal componente genitore

    function initialState() {
       return { 
         someDataParameters : '',
         someMoreDataParameters: ''
              }
      }
    
    export default {
       data() {
        return initialState();
      },
        methods: {
      clearAllData() {
      Object.assign(this.$data, initialState());
    },
    
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.