Vue集成Bootstrap4折叠卡片出现重复key警告、联动展开及过渡失效问题
问题根源
- 重复key警告:你对同一份长度为1的
pricing数组执行了3次v-for循环,三次循环生成的key都是0,触发重复key报错 - 多卡片同步展开:三张卡片绑定的是同一份
expand状态,修改任意卡片的状态都会同步到所有卡片 - 过渡效果失效:同时使用了Bootstrap原生折叠的
data-*属性和Vue状态控制show类,两套逻辑冲突导致过渡动画异常 - 存在语法错误:
data配置尾部多了冗余],methods前缺少逗号,多个方法定义之间缺少逗号 - 重复ID问题:模板中存在大量重复的固定ID,违反HTML ID唯一性规则,会导致DOM操作异常
修复方案
- 重构
pricing数组结构,每张套餐卡对应数组内一个独立元素,每个元素维护自身的套餐信息、展开状态 - 删除冗余的2次
v-for循环,仅用一次循环动态渲染所有卡片,避免重复代码和key冲突 - 移除Bootstrap原生折叠相关的
data-toggle/data-target属性,完全由Vue状态控制展开收起,避免逻辑冲突 - 合并三个重复的折叠方法为一个通用方法
- 修正JS语法错误,将重复ID改为类名
修复后完整代码
<template> <div class="prices"> <div class="container"> <h1 class="comfortHeader" style="margin-bottom: 50px;">Наши цены</h1> <div class="d-flex row no-gutters justify-content-center"> <!-- 仅一次循环渲染所有卡片,用数据唯一ID当key --> <div class="card text-center mt-3" v-for="(price, index) in pricing" :key="price.id"> <div class="card-body"> <!-- 动态渲染最优选择标签 --> <div class="sale" v-if="price.isBest">Лучший выбор!</div> <h5 class="card-title">{{price.lessonCount}} Уроков</h5> <h5 class="card-title biggerSize" :style="{color: price.isBest ? '#2FAFE5' : ''}" style="font-weight: bold; padding-bottom:5px; padding-top:15px;" > {{price.pricePer.toLocaleString()}} <span class="fas fa-tenge d-inline-block"></span> </h5> <p class="card-text card-height">за урок</p> <p class="card-text">Всего к оплате {{price.totalPrice.toLocaleString()}}тг</p> <!-- 动态渲染优惠信息 --> <p class="economyTariff" v-if="price.discount">Сэкономить {{price.discount.toLocaleString()}} тг</p> <button class="SeeTheCourse mt-5">Начать заниматься</button> <a class="collapsed d-lg-none d-md-block" aria-expanded="false" href="javascript:;" @click.prevent="toggleExpand(index)" > <span class="fa fa-chevron-down pull-bottom"></span> </a> <div v-if="price.items.length > 0" class="collapse d-lg-block" :class="{show: price.expand}" > <div v-for="(item, idx) in price.items" :key="idx"> <p class="card-text lowerbodyparagraph" :style="{borderBottom: idx === price.items.length-1 ? 'none' : ''}"> {{item}} </p> </div> </div> </div> </div> </div> </div> </div> </template> <script> import $ from 'jquery' export default { data() { return { pricing: [ // 10课套餐 { id: 1, lessonCount: 10, pricePer: 1600, totalPrice: 16000, discount: null, isBest: false, expand: false, items: [ "10 онлайн уроков", "Интерактивные задания", "Безлимитный доступ к материалам" ] }, // 30课套餐 { id: 2, lessonCount: 30, pricePer: 1300, totalPrice: 39000, discount: 9000, isBest: false, expand: false, items: [ "30 онлайн уроков", "Интерактивные задания", "Безлимитный доступ к материалам" ] }, // 60课套餐 { id: 3, lessonCount: 60, pricePer: 1000, totalPrice: 60000, discount: 16000, isBest: true, expand: false, items: [ "60 онлайн уроков", "Премиальная поддержка", "Обратная связ", "Безлимитный доступ к материалам" ] } ] } }, methods: { toggleExpand(index) { this.pricing.forEach((item, i) => { item.expand = i === index ? !item.expand : false }) } } } </script> <style scoped> .biggerSize { /* 原biggerSize样式写这里 */ } .card-height { /* 原card-height样式写这里 */ } .lowerbodyparagraph { /* 原lowerbodyparagraph样式写这里 */ } </style>
内容的提问来源于stack exchange,提问作者Nodira Yusupova
相关产品推荐
相关产品推荐

