Как установить полное свойство данных компонента для нового объекта, сохраняя реактивность в Vue? - PullRequest
0 голосов
/ 14 января 2020

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

В моем компоненте Vue (написано с использованием vue -property- у меня есть свойство data, которое является объектом:

const emptyFilters = {
    name: ''
};

export default class MyComponent extends Vue {
    filtersFields = emptyFilters;
    ...
}

В какой-то момент я бы хотел почистить фильтры. На данный момент есть только один фильтр, поэтому я могу сделать это:

        this.filtersFields.name = '';

, но чтобы эта работа работала с любым количеством фильтров, я хотел бы сделать что-то вроде этого:

        this.filtersFields = emptyFilters;

Приведенный выше метод дает сбой, предположительно потому, что я установил свойство, которое можно наблюдать для нового объекта, поэтому подписка на модель продолжает наблюдать за старым объектом, а не за новым. Насколько я понимаю, Vue.set - это то, что мне нужно использовать для установки целого this.filtersFields на новый объект (emptyFilters). Я попытался:

        this.$set(this, 'filtersFields', emptyFilters);

, но это тоже не удается (ввод с v-model="filtersFields.name" не очищается). Что я делаю неправильно? Как правильно использовать Vue.set? Он используется только для добавления нового свойства, которое не было установлено ранее? Нужно ли использовать какой-то другой метод?

PS В качестве решения , основываясь на ответах ниже, я решил не воссоздавать объект из себя, а использовать "заводской" метод получения:

// instead of using a const emptyFilters we use a getter because otherwise
// emptyFilters becomes an observable and should be recreated each time anyway
const getEmptyFilters = (): examinationsFilters => ({
    name: ''
});

...

    // (initializing)
    filtersFields: examinationsFilters = getEmptyFilters();

...

        // (in method)
        this.filtersFields = getEmptyFilters();

Ответы [ 2 ]

2 голосов
/ 14 января 2020

Как правильно указывает Иисус Гальван, это, скорее всего, вызвано вашим кодом инициализации. Допустим, у вас есть следующий шаблон:

<template>
  <div>
    <input v-model="filtersFields.firstName" type="text" />
    <input v-model="filtersFields.lastName" type="text" />
    <button @click="onReset">reset</button>
  </div>
</template>

Вот пример реализации, в которой не будет работать :

const EMPTY_FILTERS = { firstName: '', lastName: '' };

export default {
  data() {
    return { filtersFields: EMPTY_FILTERS };
  },
  methods: {
    onReset() {
      this.filtersFields = EMPTY_FILTERS;
    },
  },
};

Это не работает, потому что this.filtersFields = EMPTY_FILTERS на самом деле ничего не делает , Присвоение объекта в JS выполняется по ссылке, поэтому filtersFields уже указывает на EMPTY_FILTERS. Вот пример, который работает:

const EMPTY_FILTERS = { firstName: '', lastName: '' };

export default {
  data() {
    return { filtersFields: { ...EMPTY_FILTERS } };
  },
  methods: {
    onReset() {
      this.filtersFields = { ...EMPTY_FILTERS };
    },
  },
};

На этот раз мы всегда присваиваем копию из EMPTY_FILTERS, которая будет правильно соблюдаться Vue.

1 голос
/ 14 января 2020

Однажды у меня была похожая проблема. Это потому, что (в зависимости от того, как вы назначаете начальное состояние) вы, вероятно, все еще наблюдаете тот же объект.

Попробуйте воссоздать объект, который вы хотите назначить при каждом назначении.

const emptyFilters = {
    name: ''
};

export default class MyComponent extends Vue {
    methods: {
        setFilters () {
            let filters = JSON.parse(JSON.stringify(emptyFilters));
            this.$set(this, 'filtersFields', filters);
        },
    },
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...