Есть ли правильный способ сбросить начальные данные компонента в vuejs?

93

У меня есть компонент с определенным набором начальных данных:

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

Это данные для модального окна, поэтому, когда оно отображается, я хочу, чтобы оно начиналось с этих данных. Если пользователь отменяет из окна, я хочу сбросить все данные на это.

Я знаю, что могу создать метод для сброса данных и просто вручную вернуть все свойства данных к их исходным значениям:

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

Но это кажется действительно небрежным. Это означает, что если я когда-либо внесу изменения в свойства данных компонента, мне нужно будет убедиться, что я не забыл обновить структуру метода сброса. Это не совсем ужасно, так как это небольшой модульный компонент, но он заставляет мой мозг кричать в части оптимизации.

Решение, которое, как я думал, будет работать, будет заключаться в том, чтобы получить свойства исходных данных в readyметоде, а затем использовать эти сохраненные данные для сброса компонентов:

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

Но initialDataConfigurationобъект изменяется вместе с данными (что имеет смысл, потому что в методе чтения мы initialDataConfigurationполучаем область действия функции данных.

Есть ли способ получить данные начальной конфигурации без наследования области?

Я слишком много думаю об этом, и есть лучший / более простой способ сделать это?

Единственный вариант - жесткое кодирование исходных данных?

Крис Шмитц
источник
Вы используете v-show или v-if для отображения модального окна?
Rwd
Я использую bootstrap для css, поэтому я использую его в модальном режиме, который использует jquery для отображения и скрытия. Таким образом, оконная часть компонента всегда там, просто скрыта.
Крис Шмитц,

Ответы:

125
  1. извлечь исходные данные в функцию вне компонента
  2. используйте эту функцию для установки начальных данных в компоненте
  3. повторно используйте эту функцию для сброса состояния при необходимости.

// 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
Это сделало это. Благодарность! Я немного отредактировал ответ, но только потому, что компоненту vue требуется функция, возвращаемая для данных, а не просто объект. Ваша концепция ответов определенно работает и верна, редактирование предназначено только для учета того, как vuejs обрабатывает компоненты.
Крис Шмитц,
3
Вы правы насчет функции для свойства data, я был небрежным. Спасибо за редактирование.
Линус Борг,
13
Теперь выдает ошибку:[Vue warn]: Avoid replacing instance root $data. Use nested data properties instead.
Sankalp Singha
34
@SankalpSingha Vue 2.0 больше не позволяет вам этого делать. Object.assignВместо этого можно использовать . Вот рабочий код: codepen.io/CodinCat/pen/ameraP?editors=1010
CodinCat
3
Для этой проблемы - [Предупреждение Vue]: избегайте замены экземпляра root $ data. Вместо этого используйте вложенные свойства данных, попробуйте это. $ Data.propName = "new value";
Станислав Остапенко
33

Чтобы сбросить компонент dataв текущем экземпляре компонента, вы можете попробовать следующее:

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

Лично у меня есть абстрактный модальный компонент, который использует слоты для заполнения различных частей диалога. Когда настроенные модальные оболочки, которые абстрактно модальные, данные, указанные в слотах, принадлежат области родительского компонента . Вот вариант абстрактного модального окна, которое сбрасывает данные каждый раз, когда отображается настроенное модальное окно (код ES2015):

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

Конечно, вы можете точно настроить свою модальную реализацию - приведенное выше также может быть выполнено в каком-то cancelхуке.

Имейте в виду, что изменение $parentпараметров из дочерних элементов не рекомендуется, однако я думаю, что это может быть оправдано, если родительский компонент просто настраивает абстрактное модальное окно и ничего более.

Герты
источник
1
Этот метод теперь выдает предупреждение VueJS; см. stackoverflow.com/questions/40340561/…
Киви Шапиро
7
Осторожно, это не привязывает контекст к data. Итак, если вы используете thisв своем dataметоде, вы можете применить контекст с помощью:Object.assign(this.$data, this.$options.data.apply(this))
Ifnot
В чем преимущество этого способа перед location.reload ()?
Карлос
30

Внимание! Object.assign(this.$data, this.$options.data())Не привязывает контекст к data ().

Так что используйте это:

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

cc этот ответ был изначально здесь

Роли Роли
источник
3

Если вас раздражают предупреждения, это другой метод:

const initialData = () => ({})

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

Не нужно возиться с $ data.

srmico
источник
2

Мне пришлось сбросить данные в исходное состояние внутри дочернего компонента, вот что у меня сработало:

Родительский компонент, вызывающий метод дочернего компонента:

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

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

Дочерний компонент:

  1. определение данных во внешней функции,
  2. присвоение объекта данных функции и вне ее
  3. определение метода clearallData (), который должен вызываться родительским компонентом

    function initialState() {
       return { 
         someDataParameters : '',
         someMoreDataParameters: ''
              }
      }
    
    export default {
       data() {
        return initialState();
      },
        methods: {
      clearAllData() {
      Object.assign(this.$data, initialState());
    },
    
Армин
источник