Как добавить элемент в Vuex и не начать вычисленное значение? - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь добавить дроби в vue / vyex, все добавления произошли в геттере, поэтому после изменения некоторых полей мы запускаем вычисленное значение.

И когда я нажимаю кнопку «добавить новые дроби», ясоздать новый объект с вычисляемым свойством и получить ошибку в геттере, потому что, как я понимаю, вычисленные изменения чека и начало работы геттера работают, но нового свойства нет, и я принимаю эту ошибку: Error in v-on handler: "TypeError: Cannot read property 'denominator' of undefined"

store

export default new Vuex.Store({
  state: {
    fractions: [
      {
        id: 1,
        numerator: 0,
        denominator: 0,
      },
      {
        id: 2,
        numerator: 0,
        denominator: 0,
      },
    ],
  },
  actions,
  mutations: {
    changeInput(state, payload) {
      state.fractions.forEach((el) => {
        if (el.id === payload.id) {
          el[payload.key] = payload[payload.key];
        }
      });
    },
    addFraction(state) {
      state.fractions.push({
        id: state.fractions.length + 1,
        numerator: 0,
        denominator: 0,
      });
    },
    deleteFraction(state, id) {
      state.fractions.forEach((el, i) => {
        if (el.id === id) {
          state.fractions.splice(i, 1);
        }
      });
    },
  },
  getters: {
    takeSum(state) {
      const sum = {
        denominator: 0,
        numerator: 0,
      };
      state.fractions.reduce((prev, curr) => {
        sum.denominator = prev.denominator + curr.denominator;
        sum.numerator = prev.numerator + curr.numerator;
      });

      return sum;
    },
  },

});

вычисляемое компонентное свойство

 computed: {
    ...mapState([
      'fractions',
    ]),

    ...mapGetters([
      'takeSum',
    ]),

  },

и шаблон

<Fraction
            v-for="(fraction, index) in fractions"
            :key="index"
            :numerator=fraction.numerator
            :denominator=fraction.denominator
            :id="fraction.id"
            @changeFractionInput=changeFractionInput
            v-bind:onClick="deleteFraction"
    />
    <div>sum: {{takeSum}}</div>

1 Ответ

0 голосов
/ 27 февраля 2019

Ваша проблема в takeSum.Вы неправильно используете редуктор.

Редуктор просматривает каждый элемент массива и вычисляет из него одно значение.Это значение может быть любым, включая объект.Однако вы должны вернуть результат между каждым элементом.То, что вы возвращаете, используется в следующем цикле.Ваш код превратится в нечто вроде этого:

  const sum = state.fractions.reduce((prev, curr) => {
    const newSum = { ...prev };

    newSum.denominator = prev.denominator + curr.denominator;
    newSum.numerator = prev.numerator + curr.numerator;

    return newSum;
  });

Поскольку вы ничего не возвращали, при первом вызове редуктора (функция внутри reduce(..) вызывается с первым и вторым элементомВаш массив. Во второй раз он вызывается с prev, являющимся undefined (вы ничего не возвращали), и curr, являющимся третьим элементом в вашем массиве.


Однако я должен сказать,что вы не правильно рассчитываете сумму дробей. Если мы возьмем сумму 1/2 и 1/3, вы скажете, что сумма на самом деле составляет 2/5. Однако быстрый расчет показывает, что это неcase.

Если вы хотите сложить две дроби, вы должны убедиться, что знаменатели обоих равны. Для нашего предыдущего примера это будет 1/2 = 3/6 и 1/3 = 2/6, поэтому сумма будет 5/6. Типичная сумма a/b + c/d будет ((a*d) + (b*c)) / (b*d).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...