如何避免重新渲染由 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。
有一个子组件列表
<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。