折叠页面 css

样式可以左右滑动,可以加无数个子数据

复制代码
<!-- 主页面(如 pages/member/member.vue) -->
<template>
	<view class="member-page">
		<!-- 顶部查询栏 -->
		<view class="search-bar">
			<text class="label">账号</text>
			<input class="input" placeholder="请输入账号" value="DF993111" />
			<button class="search-btn">查询</button>
		</view>

		<!-- 会员信息:整体横向滚动容器(核心) -->
		<view class="scroll-container">
			<!-- 会员信息卡片(宽度自适应,实现横向滑动) -->
			<view class="member-card">
				<!-- 会员信息标题栏 -->
				<view class="section-title">会员信息</view>
				<!-- 会员树:引入预编译的递归组件 -->
				<view class="member-tree">
					<MemberTreeItem v-for="(item, index) in memberData" :key="index" :node="item" :level="1"
						@toggle="handleToggle" />
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	// 引入单独的递归组件(路径根据实际项目调整,components目录可直接写组件名)
	import MemberTreeItem from '../../components/MemberTreeItem.vue';

	export default {
		components: {
			MemberTreeItem // 注册组件,直接使用
		},
		data() {
			return {
				// 模拟N级会员数据(支持无限层级,可替换为接口数据)
				memberData: [{
						info: 'DF688278(1)[第100层][经理][无级别][审核时间]',
						expanded: false,
						children: [{
							info: 'DF786622(2)[第101层][经理][无级别][审核时间]',
							expanded: true,
							children: [{
								info: 'DF768677(3)[第102层][经理][无级别][审核时间]',
								expanded: true,
								children: [{
									info: 'DF282282(4)[第103层][经理][无级别][审核时间]',
									expanded: true,
									children: [{
										info: 'DF134414(5)[第104层][经理][无级别][审核时间]',
										expanded: true,
										children: [{
											info: 'DF134414(6)[第104层][经理][无级别][审核时间]',
											expanded: true,
											children: [{
												info: 'DF134414(7)[第104层][经理][无级别][审核时间]',
												expanded: false,
												children: []
											}]
										}]
									}]
								}]
							}]
						}]
					},
					{
						info: 'DF266888(02)[第107层][经理][无级别][审核时间]',
						expanded: false,
						children: []
					}
				]
			};
		},
		methods: {
			// 处理折叠/展开切换:修改节点的expanded状态
			handleToggle(node) {
				node.expanded = !node.expanded;
			}
		}
	};
</script>

<style scoped>
	/* 页面全局样式 */
	.member-page {
		background-color: #f5f5f5;
		min-height: 100vh;
		padding: 20rpx;
		box-sizing: border-box;
	}

	/* 顶部查询栏样式 */
	.search-bar {
		background-color: #ffffff;
		display: flex;
		align-items: center;
		padding: 16rpx 20rpx;
		border-radius: 4rpx;
		margin-bottom: 20rpx;
		box-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.05);
	}

	.search-bar .label {
		font-size: 28rpx;
		color: #333333;
		width: 80rpx;
	}

	.search-bar .input {
		flex: 1;
		height: 60rpx;
		border: 1rpx solid #e5e5e5;
		border-radius: 4rpx;
		padding: 0 16rpx;
		margin: 0 16rpx;
		font-size: 28rpx;
		color: #333;
	}

	.search-bar .search-btn {
		background-color: #008000;
		color: #ffffff;
		font-size: 28rpx;
		padding: 0 24rpx;
		height: 60rpx;
		border-radius: 4rpx;
		border: none;
		line-height: 60rpx;
	}

	/* 核心:会员信息整体横向滚动容器 */
	.scroll-container {
		width: 100%;
		overflow-x: auto;
		white-space: nowrap;
		-webkit-overflow-scrolling: touch;
		/* 移动端顺滑滚动 */
		background-color: #fff;
		border-radius: 4rpx;
		box-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.05);
	}

	/* 隐藏横向滚动条,优化视觉 */
	.scroll-container::-webkit-scrollbar {
		display: none;
	}

	/* 会员卡片:宽度自适应内容,最小占满屏幕 */
	.member-card {
		display: inline-block;
		width: auto;
		min-width: 100%;
		background-color: #ffffff;
		border-radius: 4rpx;
	}

	/* 会员信息标题栏 */
	.section-title {
		background-color: #f0f0f0;
		color: #666666;
		font-size: 28rpx;
		padding: 16rpx 20rpx;
		border-bottom: 1rpx solid #e5e5e5;
		white-space: nowrap;
	}

	/* 会员树容器 */
	.member-tree {
		width: auto;
	}
</style>

引入样式在components里面创建一个MemberTreeItem.vue

复制代码
<!-- components/MemberTreeItem.vue 递归组件单文件 -->
<template>
  <view class="member-item">
    <!-- 项头部:箭头 + 会员信息 -->
    <view class="item-header" @click="handleClick">
      <!-- 折叠/展开箭头,层级动态缩进 -->
      <view class="arrow-icon" :class="{ expanded: node.expanded }" :style="{ marginLeft: (level - 1) * 30 + 'rpx' }"></view>
      <!-- 会员信息文本,不换行随整体滑动 -->
      <text class="info-text">{{ node.info }}</text>
    </view>
    <!-- 递归渲染子项:仅展开且有子项时显示 -->
    <view class="child-tree" v-if="node.expanded && node.children.length > 0">
      <MemberTreeItem
        v-for="(child, cIndex) in node.children"
        :key="cIndex"
        :node="child"
        :level="level + 1"
        @toggle="$emit('toggle', $event)"
      />
    </view>
  </view>
</template>

<script>
export default {
  name: 'MemberTreeItem', // 组件名,递归调用需指定
  props: {
    // 会员节点数据(info/expanded/children)
    node: {
      type: Object,
      required: true,
      default: () => ({ info: '', expanded: false, children: [] })
    },
    // 节点层级,控制缩进
    level: {
      type: Number,
      required: true,
      default: 1
    }
  },
  emits: ['toggle'], // 声明自定义事件,避免警告
  methods: {
    // 点击切换展开/收起状态,向上传递事件
    handleClick() {
      this.$emit('toggle', this.node);
    }
  }
};
</script>

<style scoped>
/* 会员项底部分割线 */
.member-item {
  border-bottom: 1rpx solid #f0f0f0;
}
/* 项头部布局:弹性对齐,禁止换行 */
.item-header {
  display: flex;
  align-items: center;
  padding: 16rpx 20rpx 16rpx 0;
  cursor: pointer;
  white-space: nowrap;
}
/* 折叠/展开箭头:CSS绘制,替代图片 */
.arrow-icon {
  width: 24rpx;
  height: 24rpx;
  margin-right: 12rpx;
  position: relative;
  transition: transform 0.2s ease;
}
/* 未展开:右箭头 */
.arrow-icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-60%, -50%);
  width: 0;
  height: 0;
  border-top: 6rpx solid transparent;
  border-bottom: 6rpx solid transparent;
  border-left: 8rpx solid #666;
}
/* 展开:下箭头(旋转动画) */
.arrow-icon.expanded::after {
  transform: translate(-50%, -40%) rotate(90deg);
}
/* 会员信息文本样式 */
.info-text {
  font-size: 26rpx;
  color: #333333;
  line-height: 1.4;
  white-space: nowrap;
}
/* 子项容器 */
.child-tree {
  display: block;
}
</style>
相关推荐
菩提小狗2 小时前
小迪安全2022-2023|第35天:WEB攻防-通用漏洞&XSS跨站&反射&存储&DOM&盲打&劫持|web安全|渗透测试|
前端·安全·xss
这个昵称也不能用吗?2 小时前
React 19 【use】hook使用简介
前端·react.js·前端框架
web小白成长日记2 小时前
修复 Storybook MDX 中 “does not provide an export named ‘ArgsTable‘” 的实战
前端
Aotman_2 小时前
Vue <template v-for> key should be placed on the <template> tag.
前端·javascript·vue.js
A_nanda2 小时前
vue快速学习框架
前端·javascript·vue.js·学习·c#
蜗牛攻城狮2 小时前
“直接 URL 下载” vs “前端 Blob 下载”:原理、区别与最佳实践
前端·javascript·二进制流
海绵宝宝_2 小时前
Chrome强开Gemini助手教程
前端·人工智能·chrome
abments2 小时前
chrome设置启动浏览器后自动打开关闭前的页面
前端·chrome
刘一说2 小时前
Pinia状态持久化的“隐形陷阱“:为什么页面刷新后状态丢失?
前端·javascript·vue.js