Vue2组合API数组属性更新不更新

Vue2 composition API array property update not updating

我有这个组件接受数组作为 属性:

import {
  defineComponent,
  getCurrentInstance,
  toRefs,
  watch,
} from "@vue/composition-api";

import { RecommendationAnswer, RecommendationQuestion } from "@models";
import { useCalculateInitialCount } from "./calculate-count";
import { useGetAnsweredQuestions } from "./list-questions";

export default defineComponent({
  name: "StepThree",
  emits: ["onSelect"],
  props: {
    products: {
      type: Array,
      required: false,
      default: () => [],
    },
    questions: {
      type: Array,
      required: false,
      default: () => [],
    },
  },
  setup(props) {
    const instance = getCurrentInstance();
    const { products, questions } = toRefs(props);

    watch(
      products,
      (currentProducts: any[]) => {
        if (!currentProducts) return;
        const currentQuestions = <RecommendationQuestion[]>questions.value;
        useCalculateInitialCount(currentProducts, currentQuestions);
      },
      {
        immediate: true,
      }
    );

    const selectAnswer = (answer: RecommendationAnswer) => {
      answer.selected = !answer.selected;
      questions.value.forEach((question: RecommendationQuestion) => {
        question.selected = !!question.answers.find(
          (item: RecommendationAnswer) => item.selected
        );
      });
      const answeredQuestions = useGetAnsweredQuestions(
        <RecommendationQuestion[]>questions.value
      );
      instance.proxy.$emit("onSelect", {
        step: 3,
        questions: answeredQuestions,
      });
    };

    return { selectAnswer };
  },
});

只要产品数组发生变化(发生在该组件之外),就会触发 watch。 我可以看到 watch 触发,然后函数 useCalculateInitialCount 触发,这会更新 count 属性 一个答案. 这显示在模板中:

<v-col cols="6">
  <base-fade-up class="row" :duration="0.1" tag="div">
    <v-col
      class="text-center"
      cols="12"
      v-for="question in questions.slice(
        0,
        Math.ceil(questions.length / 2)
      )"
      :key="question.id"
    >
      {{ question.title }}
      <v-card
        class="w-100"
        outlined
        @click="selectAnswer(answer)"
        v-for="answer in question.answers"
        :key="answer.id"
      >
        <v-card-text class="text-center">
          {{ answer.title }} ({{ answer.count }})
        </v-card-text>
      </v-card>
    </v-col>
  </base-fade-up>
</v-col>

加载组件时,手表会触发并正确显示计数:

但是当产品更新时,即使我看到 console.log 中的变化:

模板没有更新。 有谁知道我该如何解决这个问题?

我认为这是因为您的数组没有新项目,所以对于观察者来说是具有相同数量项目的同一个数组,即使其中一个项目发生了变化。我不确定为什么你必须观看 属性 但如果你需要观看数组中的所有更改你可以尝试先制作数组的副本然后观看复制的数组

我想出了一个解决方法,创建了一个计算 属性 而不是观察产品。 整个代码如下所示:

import {
  computed,
  defineComponent,
  getCurrentInstance,
  toRefs,
  watch,
} from "@vue/composition-api";

import { RecommendationAnswer, RecommendationQuestion } from "@models";
import { useCalculateInitialCount } from "./calculate-count";
import { useGetAnsweredQuestions } from "./list-questions";

export default defineComponent({
  name: "StepThree",
  emits: ["onSelect"],
  props: {
    products: {
      type: Array,
      required: false,
      default: () => [],
    },
    questions: {
      type: Array,
      required: false,
      default: () => [],
    },
  },
  setup(props) {
    const instance = getCurrentInstance();
    const { products, questions } = toRefs(props);

    const questionsWithCount = computed(() => {
      const currentProducts = <any[]>products.value;
      const currentQuestions = [...(<RecommendationQuestion[]>questions.value)];
      if (!currentProducts?.length || !currentQuestions?.length) return;

      useCalculateInitialCount(currentProducts, currentQuestions);
      return currentQuestions;
    });

    const selectAnswer = (answer: RecommendationAnswer) => {
      answer.selected = !answer.selected;
      questions.value.forEach((question: RecommendationQuestion) => {
        question.selected = !!question.answers.find(
          (item: RecommendationAnswer) => item.selected
        );
      });
      const answeredQuestions = useGetAnsweredQuestions(
        <RecommendationQuestion[]>questions.value
      );
      instance.proxy.$emit("onSelect", {
        step: 3,
        questions: answeredQuestions,
      });
    };

    return { questionsWithCount, selectAnswer };
  },
});

这解决了问题,因为在模板中我使用了 questionsWithCount 而不是 questions