【区分vue2和vue3下的element UI Timeline 时间线组件,分别详细介绍属性,事件,方法如何使用,并举例】

在 Vue 2 和 Vue 3 中,Element UI 和 Element Plus 提供了 Timeline 时间线组件,但请注意,Element UI 是为 Vue 2 设计的,而 Element Plus 是为 Vue 3 设计的。这两个库中的 Timeline 组件在功能和用法上可能有所相似,但也会有一些差异,特别是在属性、事件和内部实现上。

然而,需要澄清的是,在 Element UI(Vue 2)的标准组件库中,并没有直接名为 el-timeline 的时间线组件。Element UI 主要提供了如 el-collapseel-table 等组件,而时间线组件可能是通过自定义实现或第三方扩展库获得的。不过,为了说明目的,我将基于 Element Plus(Vue 3)中的 el-timeline 组件来描述,并假设在 Vue 2 中你可能需要自己实现或使用类似的第三方组件。

Vue 3 + Element Plus Timeline

属性(Props)
  • placement: 时间线的方向,可选值为 topbottomleftright,默认为 top
  • reverse: 是否反向展示时间线,默认为 false
  • hide-timestamp: 是否隐藏时间戳,默认为 false
事件(Events)

Element Plus 的 el-timeline 组件通常不直接提供事件,因为时间线主要用于展示数据,而不是与用

<think>我们需要封装一个横向的Timeline组件,基于ElementPlus的Timeline。关键点:1.使用el-timeline并设置direction="horizontal"2.由于ElementPlus的Timeline默认是垂直的,改为横向后需要调整样式3.封装成组件,允许传入数据、自定义内容等组件功能设计:-支持传入数据数组,每个数据项包含时间戳、标题、描述等-支持自定义节点内容(通过插槽)-支持点击事件-支持设置当前激活项注意:横向时间线ElementPlus中已经通过direction属性支持,但样式可能需要调整,特别是时间戳连接线的位置。我们将创建一个名为HorizontalTimeline组件使用<scriptsetup>语法。组件代码:</think> 以下是在 Vue3 中将 Element Plus 的 Timeline 时间线改为横向布局并封装成可复用组件的完整解决方案: ### 横向时间线组件封装 ```vue <template> <div class="horizontal-timeline-container"> <!-- 使用 el-timeline 并设置方向为 horizontal --> <el-timeline direction="horizontal" :reverse="reverse"> <!-- 遍历传入的时间线数据 --> <el-timeline-item v-for="(item, index) in items" :key="item.key || index" :timestamp="item.timestamp" :hollow="item.hollow || hollow" :color="item.color || color" :size="size" :class="{ &#39;is-active&#39;: activeIndex === index }" class="timeline-item" @click="handleItemClick(index)" > <!-- 自定义内容插槽 --> <slot name="content" :item="item" :index="index"> <!-- 默认内容模板 --> <div class="timeline-content"> <div class="timeline-title">{{ item.title }}</div> <div v-if="item.description" class="timeline-description"> {{ item.description }} </div> </div> </slot> </el-timeline-item> </el-timeline> </div> </template> <script setup> import { ref, watch, computed } from &#39;vue&#39; // 组件属性定义 const props = defineProps({ items: { type: Array, required: true, default: () => [ { title: &#39;事件1&#39;, timestamp: &#39;2023-01-01&#39;, description: &#39;描述内容1&#39; }, { title: &#39;事件2&#39;, timestamp: &#39;2023-02-01&#39;, description: &#39;描述内容2&#39; } ] }, reverse: { type: Boolean, default: false }, hollow: { type: Boolean, default: false }, color: { type: String, default: &#39;#0bbd87&#39; // Element Plus 默认的时间线颜色 }, size: { type: String, default: &#39;large&#39;, validator: (value) => [&#39;normal&#39;, &#39;large&#39;].includes(value) }, activeIndex: { type: Number, default: -1 }, clickable: { type: Boolean, default: true } }) // 触发事件 const emit = defineEmits([&#39;item-click&#39;, &#39;update:active-index&#39;]) // 当前激活项索引 const activeItemIndex = ref(props.activeIndex) // 监听父组件传入的 activeIndex 变化 watch(() => props.activeIndex, (newVal) => { activeItemIndex.value = newVal }) // 处理时间线项点击 const handleItemClick = (index) => { if (!props.clickable) return activeItemIndex.value = index emit(&#39;update:active-index&#39;, index) emit(&#39;item-click&#39;, props.items[index], index) } </script> <style scoped> .horizontal-timeline-container { overflow-x: auto; padding: 20px 0; position: relative; } /* 横向时间线布局优化 */ :deep(.el-timeline) { white-space: nowrap; display: flex; padding: 0; position: relative; } :deep(.el-timeline-item) { display: inline-flex; flex-direction: column; align-items: center; flex: 1; min-width: 150px; padding: 0 10px; position: relative; } /* 时间戳样式 */ :deep(.el-timeline-item__timestamp) { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 8px; text-align: center; white-space: nowrap; font-size: 0.9em; } /* 节点容器 */ :deep(.el-timeline-item__node) { position: relative; z-index: 1; margin: 0 auto; } /* 连接线样式 */ :deep(.el-timeline-item__tail) { position: absolute; top: 50%; left: calc(100% - 12px); right: calc(-100% + 12px); height: 2px; transform: translateY(-50%); background-color: var(--el-timeline-node-color, #e4e7ed); } /* 去掉最后一个时间项的连接线 */ :deep(.el-timeline-item:last-child .el-timeline-item__tail) { display: none; } /* 内容区域样式 */ .timeline-content { text-align: center; margin-top: 15px; padding: 10px; border-radius: 4px; transition: all 0.3s; cursor: pointer; } .timeline-content:hover { background-color: #f5f7fa; } .timeline-title { font-weight: bold; margin-bottom: 5px; } .timeline-description { font-size: 0.85em; color: #606266; white-space: normal; text-align: center; } /* 激活项样式 */ :deep(.is-active .el-timeline-item__node) { transform: scale(1.2); box-shadow: 0 0 0 4px rgba(11, 189, 135, 0.2); } :deep(.is-active .timeline-content) { background-color: #ecf5ff; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); transform: translateY(-5px); } </style> ``` ### 组件使用 ```vue <template> <div class="demo-container"> <!-- 使用横向时间线组件 --> <HorizontalTimeline :items="timelineItems" :active-index="activeIndex" @update:active-index="activeIndex = $event" @item-click="handleItemClick" > <!-- 自定义内容模板 --> <template #content="{ item }"> <div class="custom-content" :class="{ &#39;is-active&#39;: item.isActive }"> <div class="custom-icon" :style="{ backgroundColor: item.iconBg }"> <el-icon :size="24"> <component :is="item.icon" /> </el-icon> </div> <div class="custom-title">{{ item.title }}</div> <div class="custom-status" :style="{ color: item.statusColor }"> {{ item.status }} </div> </div> </template> </HorizontalTimeline> <!-- 显示活动项详情 --> <div v-if="activeItem" class="timeline-details"> <h3>当前活动项: {{ activeItem.title }}</h3> <p>{{ activeItem.description }}</p> <p>状态: <span :style="{ color: activeItem.statusColor }">{{ activeItem.status }}</span></p> </div> </div> </template> <script setup> import HorizontalTimeline from &#39;./components/HorizontalTimeline.vue&#39; import { Calendar, Check, Document, User, Coin } from &#39;@element-plus/icons-vue&#39; import { ref, computed } from &#39;vue&#39; // 当前激活项索引 const activeIndex = ref(1) // 时间线数据 const timelineItems = ref([ { title: &#39;项目启动&#39;, timestamp: &#39;2023-01-15&#39;, description: &#39;项目正式启动,成立专项小组&#39;, status: &#39;已完成&#39;, statusColor: &#39;#67c23a&#39;, icon: Calendar, iconBg: &#39;#f0f7ff&#39; }, { title: &#39;需求分析&#39;, timestamp: &#39;2023-02-20&#39;, description: &#39;收集用户需求并完成需求文档&#39;, status: &#39;进行中&#39;, statusColor: &#39;#409eff&#39;, icon: Document, iconBg: &#39;#f0f7ff&#39;, color: &#39;#409eff&#39;, isActive: true }, { title: &#39;原型设计&#39;, timestamp: &#39;2023-03-25&#39;, description: &#39;完成界面原型用户流程设计&#39;, status: &#39;未开始&#39;, statusColor: &#39;#909399&#39;, icon: User, iconBg: &#39;#f0f7ff&#39; }, { title: &#39;开发阶段&#39;, timestamp: &#39;2023-04-30&#39;, description: &#39;进入开发编码阶段,分模块实施&#39;, status: &#39;未开始&#39;, statusColor: &#39;#909399&#39;, icon: Coin, iconBg: &#39;#f0f7ff&#39; }, { title: &#39;测试验收&#39;, timestamp: &#39;2023-06-10&#39;, description: &#39;系统测试用户验收测试&#39;, status: &#39;未开始&#39;, statusColor: &#39;#909399&#39;, icon: Check, iconBg: &#39;#f0f7ff&#39; } ]) // 计算当前活动项 const activeItem = computed(() => { return activeIndex.value >= 0 ? timelineItems.value[activeIndex.value] : null }) // 处理时间线项点击事件 const handleItemClick = (item, index) => { console.log(&#39;点击了时间线项:&#39;, item.title, &#39;索引:&#39;, index) } </script> <style scoped> .demo-container { max-width: 1200px; margin: 40px auto; padding: 20px; } .custom-content { padding: 10px; border-radius: 8px; transition: all 0.3s; } .custom-icon { margin: 0 auto 10px; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; border-radius: 50%; } .custom-title { font-weight: bold; margin: 5px 0; } .custom-status { font-size: 0.85rem; } .timeline-details { margin-top: 30px; padding: 20px; border: 1px solid #e4e7ed; border-radius: 8px; background-color: #f8f9fa; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); } </style> ``` ### 关键实现说明 1. **横向布局转换** - 使用 Element Plus Timeline 的 `direction="horizontal"` 属性实现基础横向布局 - 通过 CSS Flexbox 布局实现项的水平排列 - 调整时间戳位置,使其显示在节点上方 - 修改连接线为水平直线 2. **组件封装设计** - 使用 `defineProps` 定义可配置属性: - `items`:时间线数据数组(必填) - `reverse`:是否倒序显示 - `hollow`:是否空心节点 - `color`:节点颜色 - `size`:节点尺寸 - `activeIndex`:当前激活项的索引 - `clickable`:是否可点击 - 通过 `defineEmits` 定义事件: - `item-click`:点击项时触发 - `update:active-index`:用于实现活动索引的双向绑定 3. **交互功能实现** - 支持点击时间线项切换激活状态 - 实现活动索引的双向绑定(v-model:active-index) - 提供默认插槽具名插槽支持自定义内容 4. **样式优化** - 使用 `:deep()` 穿透选择器修改 Element Plus 组件内部样式 - 为激活项添加特殊样式效果(放大节点、背景高亮) - 添加悬浮效果增强交互体验 - 确保响应式设计,在小屏设备上自动添加水平滚动 ### 使用场景 此组件特别适用于: - 项目进度追踪(如示所示) - 操作流程展示(如订单状态跟踪) - 横向历史时间轴 - 步骤引导流程 - 任何需要水平展示时间顺序的场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加仑小铁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值