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

#javascript #vue.js #vuex #vue-reactivity

#javascript #vue.js #vuex #vue-реактивность

Вопрос:

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

  1. Отправка действия
 deleteOption(path, key) 
{ this.$store.dispatch('deleteOptionAction', {path, key}) }
  
  1. Фиксация мутации
 deleteOptionAction ({ commit }, payload) { commit('deleteOption', payload) }
  
  1. Мутация получает полезную нагрузку с path = ‘state.xmlValues.Предлагает[0].данные.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))
   }
  

Я пытался использовать синтаксис состояния [полезная нагрузка.путь] — но это не работает.
Путь включает строку ‘state.xmlValues.Предлагает[0].данные.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))
  

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

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

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

Ответ №1:

Перво-наперво: не используйте 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 amp;amp; isObjectLike(source)) {
      deletableSource = get(source, selector);
    }

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

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

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

Ответ №2:

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

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

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