以下是一个基于 Vue 的实现方案,通过为每个列表项单独维护展开状态,确保列表项之间互不影响。核心思路是为每个列表项绑定独立的 isExpanded
状态,并通过箭头图标切换状态和内容显示。
完整代码示例
组件模板(ListComponent.vue)
vue
<template>
<div class="list-container">
<div
v-for="(item, index) in list"
:key="index"
class="list-item"
>
<!-- 标题行(带箭头) -->
<div class="title-row" @click="toggleExpand(index)">
<h3>{{ item.title }}</h3>
<span class="arrow">
<!-- 箭头图标:根据展开状态切换方向 -->
<svg
xmlns="http://www.w3.org/2000/svg"
:style="{ transform: isExpanded[index]? 'rotate(180deg)' : 'rotate(0deg)' }"
width="16"
height="16"
>
<path d="M8 12L3 7 8 2 13 7 8 12Z"/>
</svg>
</span>
</div>
<!-- 展开内容 -->
<div class="content" v-show="isExpanded[index]">
<p>{{ item.content }}</p>
<!-- 其他详情内容 -->
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
// 模拟列表数据(包含标题和内容)
const list = ref([
{
title: '列表项1',
content: '这是列表项1的详细内容,点击箭头展开或收起...'
},
{
title: '列表项2',
content: '这是列表项2的详细内容,点击箭头展开或收起...'
},
{
title: '列表项3',
content: '这是列表项3的详细内容,点击箭头展开或收起...'
}
]);
// 为每个列表项维护独立的展开状态(默认关闭)
const isExpanded = ref(new Array(list.value.length).fill(false));
// 切换展开状态的方法
const toggleExpand = (index) => {
isExpanded.value[index] = !isExpanded.value[index];
};
</script>
<style scoped>
.list-container {
max-width: 600px;
margin: 0 auto;
}
.list-item {
border: 1px solid #e5e7eb;
border-radius: 8px;
margin-bottom: 16px;
overflow: hidden;
}
.title-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
cursor: pointer;
transition: background-color 0.2s;
}
.title-row:hover {
background-color: #f3f4f6;
}
.arrow {
font-size: 1.2em;
transition: transform 0.3s ease;
}
.content {
padding: 16px;
background-color: #fff;
line-height: 1.6;
}
</style>
关键实现步骤
- 使用
isExpanded
数组为每个列表项存储独立的展开状态(true
为展开,false
为收起)。 - 数组长度与列表数据长度一致,通过索引
index
关联列表项和状态。
- 在标题行绑定
@click="toggleExpand(index)"
,点击时切换对应索引的isExpanded
状态。 - 通过
v-show="isExpanded[index]"
控制详情内容的显示 / 隐藏。
- 使用 SVG 箭头图标,通过
transform: rotate()
根据展开状态旋转箭头方向(展开时旋转 180°)。 - 添加过渡动画
transition: transform 0.3s ease
使切换更平滑。
- 使用
scoped
样式确保当前组件的 CSS 不影响其他组件。 - 通过
overflow: hidden
和border-radius
实现折叠效果的视觉完整性。
效果说明
- 点击箭头:单个列表项展开 / 收起,其他列表项状态不受影响。
- 动画效果:箭头旋转和内容显示 / 隐藏带有过渡动画,提升用户体验。
- 响应式布局:列表容器宽度可通过
max-width
调整,适应不同屏幕尺寸。
扩展说明
- 数据驱动:若列表数据动态更新(如异步加载),需在数据更新后重新初始化
isExpanded
数组:
javascript
watch(list, (newVal) => {
isExpanded.value = new Array(newVal.length).fill(false);
}, { deep: true });
- 自定义图标:可替换 SVG 图标为 Vant 组件库的
ArrowUp
/ArrowDown
图标,或使用字体图标库(如 Font Awesome)。 - 性能优化:若列表项过多,可使用
vue-virtual-scroller
实现虚拟列表,提升渲染性能。