Vue问答组件展开/收起全部功能异常修复请求
你的代码同时混用了两种状态控制逻辑:单条问答的expanded属性,以及全局的expand、show、showIndex变量。点击「全部展开」后expand设为true,此时所有问答靠expand变量显示;但点击单个收起按钮时,hideAnswer方法会把expand设为false,并且在!this.expand的判断下遍历关闭所有问答的expanded状态,导致全部问答被关闭。
统一用每条问答自身的expanded属性控制显示,去掉冗余的全局状态变量(show、showIndex),让全局按钮仅批量修改所有问答的expanded值,单个按钮仅修改当前条的expanded值。
步骤1:修改模板的显示判断
把问答内容的v-if条件从依赖全局状态改为仅依赖当前问答的expanded状态:
<!-- 原代码 --> <div v-if="(show && showIndex === index) || expand" style="overflow:auto;padding:1rem;padding-left: 30px;"> <!-- 修改后 --> <div v-if="techQuest.expanded" style="overflow:auto;padding:1rem;padding-left: 30px;">
同时修正投票区域的判断逻辑(移除无效的techQuest.index === index判断,保留投票禁用的核心逻辑):
<!-- 原代码 --> <td v-if="(!techQuest.voteDisable && techQuest.index === index)"> <!-- 修改后 --> <td v-if="!techQuest.voteDisable">
删除模板中冗余的<div v-else style="display: none"></div>,v-if不满足时元素本身不会渲染,无需额外占位。
步骤2:重构JS方法
删除全局变量show、showIndex,修改各方法逻辑如下:
单个展开方法(showAnswer)
如果需要单选模式(展开当前问答时关闭其他所有):
showAnswer: function(value) { this.showThanks = false; this.showQuestThanks = false; // 关闭所有问答 this.questionList.questions.forEach(item => { item.expanded = false; }); // 打开当前问答 this.questionList.questions[value].expanded = true; }
如果需要多选模式(仅切换当前问答状态,不影响其他),删除遍历关闭的代码即可:
showAnswer: function(value) { this.showThanks = false; this.showQuestThanks = false; this.questionList.questions[value].expanded = true; }
单个收起方法(hideAnswer)
仅关闭当前问答,不再修改全局状态或遍历操作所有条目:
hideAnswer: function(value) { this.showThanks = false; this.showQuestThanks = false; this.questionList.questions[value].expanded = false; }
全部展开方法(expandAll)
批量设置所有问答的expanded为true:
expandAll: function() { this.questionList.questions.forEach(item => { item.expanded = true; }); }
全部收起方法(collapseAll)
批量设置所有问答的expanded为false:
collapseAll: function() { this.questionList.questions.forEach(item => { item.expanded = false; }); this.showThanks = false; this.showQuestThanks = false; }
最终完整代码片段
模板部分
<div v-for="(techQuest, index) in questionList.questions" :key="index"> <div class="tech-qa-question"> <a href="javascript:void(0);" style="color:#2b91ca;padding-right:2px;" v-show="!techQuest.expanded" :id="'showAns_'+index" @click="showAnswer(index)"> <img border="0" src="/images/icons/gray-plus.png"> </a> <a href="javascript:void(0);" style="color:#2b91ca;padding-right:2px;" v-show="techQuest.expanded" :id="'hideAns_'+index" @click="hideAnswer(index)"> <img border="0" src="/images/icons/gray-minus.png"> </a> <span style="color: #007185;">{{techQuest.question}}</span> </div> <div v-if="techQuest.expanded" style="overflow:auto;padding:1rem;padding-left: 30px;"> <div v-html="techQuest.answer.answer"></div> <div class="tech-qa-adc"> By Member </div> <table class="tech-qa-ballot"> <tr> <td> Did you find this answer helpful? </td> <td v-if="!techQuest.voteDisable"> <a href="javascript:void(0);" @click="castVote(techQuest.answer.answerId,'1',index,1)"> <i class='fas fa-solid fa-thumbs-up' style="color:#0d72c2;padding-right:10px;padding-left:5px;" aria-hidden='true'></i> </a> <a href="javascript:void(0);" @click="castVote(techQuest.answer.answerId,'-1',index,1)"> <i class='fas fa-solid fa-thumbs-down' style="color:#0d72c2" aria-hidden='true'></i> </a> </td> <td v-else> <a href="javascript:void(0);" class="disable"> <i class='fas fa-solid fa-thumbs-up' style="color:darkgrey;padding-right:10px;padding-left:5px;" aria-hidden='true'></i> </a> <a href="javascript:void(0);" class="disable"> <i class='fas fa-solid fa-thumbs-down' style="color:darkgrey" aria-hidden='true'></i> </a> </td> <td style="color: green;" v-show="showThanks && techQuest.expanded"> Thanks for your feedback! </td> </tr> </table> </div> <hr aria-hidden="true" style="border-top: 1px solid #e7e7e7;border-bottom-width: 0;background-color: transparent;"> </div>
JS方法部分
showAnswer: function(value) { this.showThanks = false; this.showQuestThanks = false; // 单选模式保留此遍历,多选模式删除即可 this.questionList.questions.forEach(item => { item.expanded = false; }); this.questionList.questions[value].expanded = true; }, hideAnswer: function(value) { this.showThanks = false; this.showQuestThanks = false; this.questionList.questions[value].expanded = false; }, collapseAll: function() { this.questionList.questions.forEach(item => { item.expanded = false; }); this.showThanks = false; this.showQuestThanks = false; }, expandAll: function() { this.questionList.questions.forEach(item => { item.expanded = true; }); }, // 保留原有投票逻辑 castVote: function(answerId, vote, index, type) { // 你的原有投票逻辑 this.questionList.questions[index].voteDisable = true; this.showThanks = true; }
说明
现在所有问答的显示/收起完全由自身的expanded属性控制,状态逻辑清晰,不会再出现全局状态与单条状态冲突的问题。可根据需求选择单选或多选模式,投票区域的感谢提示也会仅在当前展开的问答下显示。
内容的提问来源于stack exchange,提问作者Swe

