如何避免重新渲染由 v-for 指令创建的所有子组件

How to avoid rerendering all child components which are created by v-for directive

有一个子组件列表

 <question-list-item
        v-for="(item, index) in questionListParsed"
        :key="item.id"
        :both-question="item"
        :class-id="classId"
        :subject-id="subjectId"
        :index="index+1"
      />

questionListParsed 是 vuex 中的 getter。

  /**************************************************************************
   * getters
   **************************************************************************/
  get questionListParsed(): QuestionListItemRes[] {
    const { questionList, showingOriginalQuestion } = this
    const questionListParsed = questionList.map((e) => {
      const recommendQuestion = e.recommendedQuestions[0]
      const recommendQuestionIds = showingOriginalQuestion[e.questionNumber]
      let arr = []
      if (recommendQuestionIds) {
        arr = recommendQuestionIds.filter((item) => {
          return !this.removedRecommendQuestionIds.includes(item)
        })
      }
      return {
        recommendQuestion: {
          ...recommendQuestion,
          stem: recommendQuestion.question,
          knowledges: splitMultiKnowledge(recommendQuestion.knowledge),
          questionSourceList: recommendQuestion.sources,
          categoryId: recommendQuestion.categoryId,
        },
        originalQuestion: {
          ...e,
          id: e.questionNumber,
          stem: e.question,
          difficulty: e.complexity,
          knowledges: splitMultiKnowledge(e.knowledge),
        },
        id: recommendQuestion.id, 
        questionSimilarId: e.questionNumber, 
        mistakeAnswerId: e.id,
        targetExerciseId: e.targetExerciseId,
        status: recommendQuestion.status,
      }
    })

    return questionListParsed
  }

questionListParsed 主要取决于状态 questionList whitch 是来自服务器端的原始数据。现在我通过以下方式更改 questionList

  @Mutation
  updateQuestionListByIndex(data: UpdateParams): void {
    if (data.value) {
      const temp = [...this.questionList]
      temp[data.index] = data.value
      this.questionList = temp
    }
  }

并在像这样的 Action 中提交突变

        this.context.commit('updateQuestionListByIndex', {
          index: targetIndex,
          value: originQuestion[0],
        })

我只想更改数组 questionList 中的一项,然后 questionListParsed 更改。 期望是只有一个组件更新但所有子组件都更新(在其更新的飞节[=中使用console.log('updated') 35=]).

怎么做?

之所以更新所有组件是因为你使用了计算属性(Vuex getter 是Vue 计算属性)。

每当 questionList 中的任何内容发生更改时,都会重新计算 questionListParsed,并且因为您正在使用 map 并生成新的 objects,结果是一个具有完整的新数组new objects --> 列表中的每个 child 都会更新

我不认为这是一个问题,因为实际上只有更改项目的 DOM 元素会更新(这就是虚拟 DOM 的优点)。如果您确实看到一些性能问题,解决它的方法是停止使用 computed/getters,而是仅在加载数据时进行一次转换,并继续仅使用 questionListParsed

您不需要阻止子组件重新渲染,Vue 会为您完成。通过为每个列表元素提供一个唯一的键 :key="item.id",您可以为 Vue 提供有关该项目的提示,以便 Vue 可以识别和重用已经呈现的部分。

有关详细信息,请参阅 https://vuejs.org/v2/api/#key