Как удалить записи из хранилища Vuex, используя динамический путь в качестве полезной нагрузки для мутации?

Я хочу создать мутацию для состояния vuex, но заставить его динамически обновлять состояние - чтобы полезная нагрузка включала путь к объекту, из которого я хочу удалить элемент, и ключ.

  1. Отправка действия
deleteOption(path, key) 
{ this.$store.dispatch('deleteOptionAction', {path, key}) }
  1. Совершение мутации
deleteOptionAction ({ commit }, payload) { commit('deleteOption', payload) }
  1. Мутация получает полезную нагрузку с path = 'state.xmlValues.Offers [0] .data.Pars' и key = 0.
deleteOption (state, payload) { 
  let stt = eval('state.' + payload.path)
  Vue.delete(stt, payload.key)
  // delete stt[payload.key] - works the same as Vue.delete
  state.xmlValues.Offers[0].data.Pars = Object.assign({}, Object.values(stt))
   }

Я пробовал использовать синтаксис состояния [payload.path], но это не сработало. Путь включает строку 'state.xmlValues.Offers [0] .data.Pars', поэтому для ее работы я использовал let stt = eval ('state.' + Payload.path). Но затем удалить элемент из состояния становится сложно: при использовании Vue.delete (stt, payload.key) - он удалит только ключ элемента, локально сохраненный в переменной stt, а не в состоянии.

Затем я переназначил объекты состояния с помощью stt (из которого нужный элемент уже удален), жестко закодировав путь - и этого я стараюсь избегать:

state.xmlValues.Offers[0].data.Pars = Object.assign({}, Object.values(stt))

Как передать путь к магазину, а затем использовать его для удаления объекта в состоянии без явного жесткого кодирования пути?

Что касается другого моего addOption для мутации, я также использовал динамический путь к объекту состояния - и он отлично работает при использовании динамического пути, оцениваемого в stt

addOption (state, payload) {
      let stt = eval('state.' + payload.path)
      Vue.set(stt, payload.key, payload.newEl)
   }

person me-and-viy    schedule 09.04.2019    source источник


Ответы (2)


Перво-наперво: не используйте eval(..). Всегда. Эта функция позволяет выполнять произвольный код, и вы ничего не делаете для очистки значения!

Более разумным вариантом было бы самому разобрать свой путь. Вы можете написать что-нибудь самостоятельно, но lodash уже имеет для этого функцию toPath. Он возвращает массив с каждой частью того, что мы пытаемся получить.

Теперь, когда мы знаем, как добраться до ключа, который хотим удалить, мы могли бы написать код, который проверяет, существует ли каждая часть и является ли каждая часть объектом или массивом. Но поскольку теперь мы используем lodash, мы могли бы облегчить себе жизнь, используя _.get и _.isObjectLike:

import { toPath, get, isObjectLike } from 'lodash-es';

function deletePath(source, pathStr) {
    const path = toPath(pathStr);

    const selector = path.slice(0, -1);
    const key = path[path.length - 1];

    let deletableSource = source;

    if (selector.length && isObjectLike(source)) {
      deletableSource = get(source, selector);
    }

    if (isObjectLike(deletableSource)) {
      // We can delete something from this!
      this.$delete(deletableSource, key);
    }
}

Теперь, когда у нас есть это, мы можем сделать что-то вроде назначения его прототипу Vue или экспортировать его в качестве вспомогательной функции. Я перепишу ваш addOption как упражнение для читателя.

 Edit Как удалить записи из хранилища Vuex, используя динамический путь в качестве полезной нагрузки для мутации?

person Sumurai8    schedule 09.04.2019

Благодаря @ Sumurai8 я понял, что можно передать параметр не как строку, а на самом деле ссылку на магазин вот так. Так что не нужно передавать жало с путем к объекту в состоянии.

<button @click="deleteOption($store.state.xmlValues.Offers[mainData.curOfferKey].data.Pars)">delete</button>

Функции lodash get и toPath также были очень полезны!

person me-and-viy    schedule 14.04.2019