Правильный способ использования Vuex с дочерними компонентами

Раньше я использовал VueJS и Vuex. Не в производстве, просто для некоторых простых личных побочных проектов, и это было довольно прямолинейно.

Однако теперь я столкнулся с проблемой, которая немного сложнее, но использование Vuex уже кажется намного более сложным. Поэтому я ищу некоторые рекомендации здесь.

В главном представлении я представляю пользователю список карточек. Карта представляет собой редактируемую форму примерно десяти свойств (вводы, выбор и т. д.). Я, очевидно, реализовал компонент для этих карт, так как они повторяются в виде списка. Мой первый наивный подход заключался в том, чтобы получить список — назовем это формами — из моего магазина, а затем с помощью v-for представить карточку для каждой формы в этом списке форм. Форма передается дочернему компоненту как свойство.

Теперь я хочу привязать элементы управления формы к свойствам. Для этого я реализовал Двусторонние вычисляемые свойства, чтобы правильно использовать мутации моего хранилища. Но реализация пользовательского вычисляемого свойства с геттером и сеттером плюс мутация для каждого свойства в моей модели кажется чрезвычайно повторяющейся. Кроме того, в моем состоянии формы представляют собой массив. Поэтому я должен передать идентификатор формы для редактирования в магазине каждой мутации.

Что-то еще, что я имел в виду, это просто передать идентификатор хранилища формы дочернему компоненту и иметь геттеры «по идентификатору» для каждого свойства моей модели, а также соответствующую мутацию. Но это тоже не похоже на правильный способ сделать это. По сути то же самое, верно?!

Есть ли лучшее решение этой проблемы? Может быть, я просто что-то упускаю или усложняю.

Урезанный пример:

Editor.vue:

<template>
  <v-container>
    <EditableCard v-for = "(card, i) in cards" :key = "i" :card = "card" />
  </v-container>
</template>

<script>
import EditableCard from "@/components/EditableCard";

import { mapGetters } from "vuex";

export default {
  name: "Editor",

  components: {
    EditableCard
  },

  computed: {
    ...mapGetters("cards", {
      cards: "list"
    })
  }
};
</script>

EditableCard:

<template>
  <v-card>
    <v-form>
      <v-card-title>
        <v-text-field v-model = "title"></v-text-field>
      </v-card-title>

      <v-card-text>
        <v-text-fieldv-model = "text"></v-text-field>
        <!-- And some more fields... -->
      </v-card-text>
    </v-form>
  </v-card>
</template>

<script>
import { mapMutations } from "vuex";

export default {
  name: "EditableCard",

  props: {
    card: Object
  },

  computed: {
    title: {
      get() {
        return card.title;
      },
      set(value) {
        this.setCardTitle(this.card.id, value);
      }
    },

    text: {
      get() {
        return card.text;
      },
      set(value) {
        this.setCardText(this.card.id, value);
      }
    }

    // Repeat for every form input control
  },

  methods: {
    ...mapMutations("cards", {
      setCardTitle: "setTitle",
      setCardText: "setText"

      // Repeat for every form input control
    })
  }
};
</script>

Вы хотите, чтобы ваши формы редактировались в режиме реального времени или, скорее, изменялись сразу после нажатия кнопки «Сохранить»?

Maciej Kwas 23.12.2020 01:41

Можете ли вы привести самый простой пример того, что вы описываете?

Robert 23.12.2020 01:47

В режиме реального времени. Вот почему я пытаюсь использовать v-модель с вычисляемыми свойствами. Но отображение этого с помощью Vuex кажется излишним.

LuMa 23.12.2020 01:48

Используйте индекс и устанавливайте весь объект формы в одном вычисляемом установщике всякий раз, когда изменяется какое-либо поле.

Dan 23.12.2020 02:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
1 047
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Было бы неплохо создать вычисляемый установщик для всего объекта формы с помощью клона, но это не сработает, поскольку изменения не вызовут срабатывания вычисляемого установщика.

If anyone wants to explore this interesting failure, see here)

Чтобы обойти это, вы можете использовать часы и клон данных:

<v-form>
  <v-text-field v-model = "clone.title" />
  <v-text-field v-model = "clone.text" />
</v-form>
props: ['index', 'card'],
data() {
  return {
    clone: {}
  }
},
watch: {
  card: {
    handler(card) {
      this.clone = { ...card }
    },
    immediate: true,
    deep: true
  },
  clone: {
    handler(n,o) {
      if (n === o) {
        this.$store.commit('SET_CARD', { index: this.index, card: n })
      }
    },
    deep: true
  }
}

Ваш v-for:

<EditableCard v-for = "(card, index) in cards" :card = "card" :index = "index" :key = "index" />

Мутация:

mutations: {
  SET_CARD(state, { index, card }) {
    Vue.set(state.cards, index, card);
  }
}

Это намного сложнее, чем должно быть... но это работает.

Другие вопросы по теме