Czy istnieje właściwy sposób resetowania początkowych danych komponentu w vuejs?

93

Mam komponent z określonym zestawem danych początkowych:

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

To są dane dla okna modalnego, więc kiedy się wyświetli, chcę, aby zaczęło się od tych danych. Jeśli użytkownik zrezygnuje z okna, chcę zresetować wszystkie dane do tego.

Wiem, że mogę utworzyć metodę resetowania danych i po prostu ręcznie przywrócić wszystkie właściwości danych do ich oryginalnych:

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

Ale to wydaje się naprawdę niechlujne. Oznacza to, że jeśli kiedykolwiek dokonam zmiany we właściwościach danych komponentu, będę musiał upewnić się, że pamiętam o zaktualizowaniu struktury metody resetowania. To nie jest absolutnie straszne, ponieważ jest to mały modułowy komponent, ale sprawia, że ​​część optymalizacyjna w moim mózgu krzyczy.

Rozwiązaniem, które moim zdaniem zadziałałoby, byłoby pobranie początkowych właściwości danych w readymetodzie, a następnie użycie tych zapisanych danych do zresetowania komponentów:

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

Ale initialDataConfigurationobiekt zmienia się wraz z danymi (co ma sens, ponieważ w metodzie read initialDataConfigurationuzyskujemy zakres funkcji data.

Czy istnieje sposób na pobranie początkowych danych konfiguracyjnych bez dziedziczenia zakresu?

Czy za bardzo się nad tym zastanawiam i jest lepszy / łatwiejszy sposób na zrobienie tego?

Czy zakodowanie początkowych danych na stałe jest jedyną opcją?

Chris Schmitz
źródło
Czy używasz v-show czy v-if do wyświetlenia modalu?
RWD
Używam bootstrap dla css, więc używam jego wbudowanego modalu, który wykorzystuje jquery do pokazywania i ukrywania. Zasadniczo więc część okna komponentu jest zawsze obecna, tylko ukryta.
Chris Schmitz,

Odpowiedzi:

125
  1. wyodrębnia dane początkowe do funkcji poza komponentem
  2. użyj tej funkcji, aby ustawić dane początkowe w komponencie
  3. ponownie użyj tej funkcji, aby zresetować stan w razie potrzeby.

// 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
źródło
5
Zrobiło to. Dzięki! Zrobiłem małą edycję odpowiedzi, ale tylko dlatego, że komponent vue wymaga funkcji zwracanej dla danych, a nie tylko obiektu. Twoja koncepcja odpowiedzi na pewno działa i jest poprawna, edycja dotyczy tylko tego, jak vuejs obsługuje komponenty.
Chris Schmitz,
3
Masz rację co do funkcji właściwości data, czyli ja byłem niechlujny. Dzięki za edycję.
Linus Borg
13
Teraz wyświetla błąd:[Vue warn]: Avoid replacing instance root $data. Use nested data properties instead.
Sankalp Singha
34
@SankalpSingha Vue 2.0 nie pozwala już na to. Możesz użyć Object.assignzamiast tego. Oto działający kod: codepen.io/CodinCat/pen/ameraP?editors=1010
CodinCat
3
W przypadku tego problemu - [Vue warn]: Unikaj zastępowania danych $ root instancji. Zamiast tego użyj zagnieżdżonych właściwości danych, spróbuj tego. $ Data.propName = "nowa wartość";
Stanislav Ostapenko
33

Aby zresetować komponent dataw bieżącej instancji komponentu, możesz spróbować tego:

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

Prywatnie mam abstrakcyjny komponent modalny, który wykorzystuje sloty do wypełniania różnych części okna. Gdy dostosowany modal otacza ten abstrakcyjny modal, dane, o których mowa w gniazdach, należą do zakresu komponentu nadrzędnego . Oto opcja abstrakcyjnego modalu, który resetuje dane za każdym razem, gdy wyświetlany jest niestandardowy modal (kod ES2015):

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

Możesz oczywiście dostroić swoją implementację modalną - powyższe może być również wykonane w jakimś cancelhooku.

Należy pamiętać, że mutacja $parentopcji z child nie jest zalecana, jednak myślę, że może to być uzasadnione, jeśli komponent nadrzędny tylko dostosowuje abstrakcyjny modalny i nic więcej.

gertas
źródło
1
Ta technika daje teraz ostrzeżenie VueJS; patrz stackoverflow.com/questions/40340561/…
Kivi Shapiro
7
Uwaga, to nie wiąże kontekstu data. Więc jeśli używasz thisw swojej datametodzie, możesz zastosować kontekst za pomocą:Object.assign(this.$data, this.$options.data.apply(this))
Ifnot
Jaka jest zaleta tego sposobu w porównaniu z location.reload ()?
Carlos
30

Uwaga, Object.assign(this.$data, this.$options.data())nie wiąże kontekstu z danymi ().

Więc użyj tego:

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

cc ta odpowiedź była pierwotnie tutaj

roli roli
źródło
3

Jeśli denerwują Cię ostrzeżenia, jest to inna metoda:

const initialData = () => ({})

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

Nie musisz majstrować przy danych $ data.

srmico
źródło
2

Musiałem zresetować dane do oryginalnego stanu wewnątrz komponentu podrzędnego, oto co mi zadziałało:

Komponent nadrzędny, wywołujący metodę komponentu potomnego:

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

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

Komponent podrzędny:

  1. definiowanie danych w funkcji zewnętrznej,
  2. przypisanie obiektu danych do funkcji i poza nią
  3. definiowanie metody clearallData (), która ma być wywoływana przez komponent nadrzędny

    function initialState() {
       return { 
         someDataParameters : '',
         someMoreDataParameters: ''
              }
      }
    
    export default {
       data() {
        return initialState();
      },
        methods: {
      clearAllData() {
      Object.assign(this.$data, initialState());
    },
    
Armin
źródło