以下是一个基于 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实现虚拟列表,提升渲染性能。 










