十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Vue3时间轴(Timeline)

Vue3时间轴(Timeline) Vue2时间轴Timeline可自定义设置以下属性时间轴内容数组items类型Item[]默认 []时间轴区域总宽度width类型number|string单位 px默认 100%时间线样式lineStyle类型 solid | dashed | dotted默认 solid通过设置 mode 可以改变时间轴和内容的相对位置mode类型left | center | right默认 left当 mode 为 center 时内容交替展现内容从左边left开始或者右边right开始展现position类型left | right默认left时间轴内容Itemdesc文字描述类型string | slot默认 undefinedcolor?圆圈颜色类型blue | green | red | gray | string默认 blue效果如下图在线预览①创建时间轴组件Timeline.vuescript setup langts import { ref, computed, watchEffect } from vue export interface Item { desc: string // 文字描述 string | slot color?: blue | green | red | gray | string // 圆圈颜色默认值 blue } export interface Props { items?: Item[] // 时间轴内容数组 width?: number | string // 时间轴区域总宽度单位 px lineStyle?: solid | dashed | dotted // 时间线样式 mode?: left | center | right // 通过设置 mode 可以改变时间轴和内容的相对位置 position?: left | right // 当 mode 为 center 时内容交替展现内容从左边left开始或者右边right开始展现 } const props withDefaults(definePropsProps(), { items: () [], width: 100%, lineStyle: solid, mode: left, position: left }) // 颜色主题对象 enum ColorStyle { blue #1677ff, green #52c41a, red #ff4d4f, gray #00000040 } const descRef ref() const dotsHeight refstring[]([]) const totalWidth computed(() { if (typeof props.width number) { return ${props.width}px } else { return props.width } }) const len computed(() { return props.items.length }) function getDotsHeight() { for (let n 0; n len.value; n) { dotsHeight.value[n] getComputedStyle( descRef.value[n].firstElementChild || descRef.value[n], null ).getPropertyValue(line-height) } } watchEffect( () { getDotsHeight() }, { flush: post } ) watchEffect( () { if (props.mode center) { for (let n 0; n len.value; n) { if ((n 1) % 2) { // odd if (props.position left) { descRef.value[n].classList.add(desc-alternate-left) } else { descRef.value[n].classList.add(desc-alternate-right) } } else { // even if (props.position left) { descRef.value[n].classList.add(desc-alternate-right) } else { descRef.value[n].classList.add(desc-alternate-left) } } } } }, { flush: post } ) /script template div classtimeline-wrap :stylewidth: ${totalWidth}; div classtimeline-item :class{ item-last: index items.length - 1 } v-for(item, index) in items :keyindex span classtimeline-tail :classtail-${mode} :styleborder-left-style: ${lineStyle};/span div classtimeline-dot :classdot-${mode} :styleheight: ${dotsHeight[index]} slot namedot :itemitem :indexindex span classdot-item v-ifitem.color red :style{ borderColor: ColorStyle.red }/span span classdot-item v-else-ifitem.color gray :style{ borderColor: ColorStyle.gray }/span span classdot-item v-else-ifitem.color green :style{ borderColor: ColorStyle.green }/span span classdot-item v-else-ifitem.color blue :style{ borderColor: ColorStyle.blue }/span span classdot-item v-else :style{ borderColor: item.color || ColorStyle.blue }/span /slot /div div refdescRef :classtimeline-desc desc-${mode} slot namedesc :itemitem :indexindex{{ item.desc || -- }}/slot /div /div /div /template style langless scoped .timeline-wrap { font-size: 14px; color: rgba(0, 0, 0, 0.88); line-height: 1.5714285714285714; .timeline-item { position: relative; padding-bottom: 30px; .timeline-tail { position: absolute; top: 12px; width: 0; height: 100%; border-left-width: 2px; border-left-color: #e8e8e8; } .tail-left { left: 5px; } .tail-center { left: 0; right: 0; margin: 0 auto; } .tail-right { right: 5px; } .timeline-dot { position: absolute; display: flex; align-items: center; :deep(svg) { fill: currentColor; } .dot-item { display: inline-block; width: 12px; height: 12px; border-width: 2px; border-style: solid; border-radius: 50%; background: #fff; } } .dot-left { left: 6px; transform: translateX(-50%); } .dot-center { left: 50%; transform: translateX(-50%); } .dot-right { right: 6px; transform: translateX(50%); } .timeline-desc { font-size: 14px; line-height: 1.5714285714285714; word-break: break-all; } .desc-left { margin-left: 25px; } .desc-center { width: calc(50% - 12px); } .desc-alternate-left { text-align: end; } .desc-alternate-right { margin-left: calc(50% 12px); } .desc-right { margin-right: 25px; text-align: end; } } .item-last { .timeline-tail { display: none; } } } /style②在要使用的页面引入script setup langts import Timeline from ./Timeline.vue import { ref } from vue import { ClockCircleOutlined } from ant-design/icons-vue import type { TimelineItem } from vue-amazing-ui const timelineItems refTimelineItem[]([ { desc: Create a services site 2023-05-24, color: green }, { desc: Solve initial network problems 1 Solve initial network problems 2 2023-05-24, color: red }, { desc: Technical testing 2023-05-24, color: blue }, { desc: Network problems being solved 2023-05-24 }, { desc: Network problems being solved 2, color: gray } ]) /script template div h1{{ $route.name }} {{ $route.meta.title }}/h1 h2 classmt30 mb10基本使用/h2 Timeline :itemstimelineItems / h2 classmb10自定义样式/h2 Timeline :itemstimelineItems template #dot{ index } span classbig-dot v-ifindex 2/span ClockCircleOutlined v-ifindex 3 stylefont-size: 16px; color: #1668dc; background: #fff; border-radius: 50% / /template template #desc{ index } p classdesc v-ifindex 2Create a services site/p /template /Timeline h2 classmb10使用虚线/h2 Timeline :itemstimelineItems line-styledashed / h2 classmb10右侧时间轴点/h2 Timeline :itemstimelineItems moderight :width540 / h2 classmb10中间时间轴点/h2 h3 classmb10内容从左边开始交替展现/h3 Timeline :itemstimelineItems modecenter :width540 template #dot{ index } span classbig-dot v-ifindex 2/span /template /Timeline h3 classmb10内容从右边开始交替展现/h3 Timeline :itemstimelineItems modecenter positionright :width640 template #dot{ index } span classbig-dot v-ifindex 2/span /template /Timeline h3 classmb10水平时间轴/h3 Timeline horizontal :itemstimelineItems template #dot{ index } span classbig-dot v-ifindex 2/span /template /Timeline /div /template style langless scoped .big-dot { display: inline-block; width: 18px; height: 18px; border: 4px solid #1677ff; border-radius: 50%; background: #fff; } .desc { font-size: 16px; font-weight: 500; } /style
返回列表