共计 4858 个字符,预计需要花费 13 分钟才能阅读完成。
本篇文章记录仿写一个
el-timeline
组件细节,从而有助于大家更好了解饿了么 ui 对应组件具体工作细节。本文是 elementui 源码学习仿写系列的又一篇文章,后续闲暇了会不断更新并仿写其余组件。源码在 github 上,大家能够拉下来,npm start 运行跑起来,联合正文有助于更好的了解。github 仓库地址如下:github.com/shuirongshu…
组件剖析
组件形成局部
工夫线组件形成局部可分为四局部:
- 工夫线小圆点
- 工夫线竖线条
- 工夫戳
- 具体内容详情
如下图:
所以针对工夫线组件的需要,次要是从这四个角度去管制。个别工夫线组件需要如下:
组件需要剖析
对于分割线的组件,个别应用的场景需要有:
- 比方依照工夫线正序或顺叙的展现(如:日志记录)
- 比方默认的工夫线小圆点的款式色彩,以及能够自定义色彩(这里默认蓝色圆环)
- 比方也能够应用小图标代替工夫线小圆点(例,应用饿了么图标)
- 应用了饿了么小图标,有时候还须要给图标上色
- 比方管制工夫戳和具体内容详情的地位(这里默认工夫戳在上方,有时候工夫戳可能在下方)
- 有的时候,可能不须要展现工夫戳,只须要展现内容,所以要再加一个是否暗藏工夫戳的变量
对于官网组件的集体认识:
1. 官网组件的 provide
和inject
能够拿掉,如下图:
2. 官网组件管制工夫戳地位用了两份 dom
,能够更改为一份dom
搭配弹性盒方向管制
3. 参考各方对仿写封装组件做一个 简洁的解决
大家能够看一下 antd 和 iview 的工夫线组件,参数确实是比饿了么的工夫线组件少一些。
antd:https://ant.design/components…
iview:https://www.iviewui.com/view-…
个人观点不肯定对,仅供参考
组件中回顾知识点
温故而知新
this.$slots.default.reverse()
默认插槽数组this.$slots.default
,也是数组,所以也是能够应用数组的办法的。
这里管制工夫线的正序顺叙就是应用了,这个办法
:style 中写四元表达式
冒号 style 其实也是能够写三元、或者四元或者更多元的,蕴含变量的表达式,如下:
<div
class="dots"
:style="{
border: elementIcon
? 'none'
: borderColor
? `2px solid ${borderColor}`
: '2px solid #1890ff',
}"
>
</div>
粗心:通过 :style
给class
为 dots
的dom 元素
设置 border
边框款式,具体边框的值取决于 elementIcon
和borderColor
这两个变量的值。
代码
演示的话,间接复制粘贴即可应用。当然残缺的代码在 github 上哦^_^
咱们先看一下效果图,再看一下代码
效果图
应用组件代码
<template>
<div>
<!-- 一般应用工夫正序排列 -->
<button @click="reverse = !reverse"> 点击更改工夫线排序 </button>
<my-timeline style="margin-top: 6px" :reverse="reverse">
<my-timeline-item timestamp="2018-01-01"
>2018 年好像还在昨天一样 </my-timeline-item
>
<my-timeline-item timestamp="2020-01-01"
>2020 就像刚刚过来一样 </my-timeline-item
>
<my-timeline-item timestamp="2022-01-01"
>2022 年也曾经走完一半了 </my-timeline-item
>
</my-timeline>
<br />
<!-- 自定义工夫线圆点色彩或应用饿了么小图标 -->
<my-timeline>
<my-timeline-item
v-for="(item, index) in timeArr"
:key="index"
:timestamp="item.timestamp"
:borderColor="item.borderColor"
:elementIcon="item.elementIcon"
:iconColor="item.iconColor"
>{{item.content}}</my-timeline-item
>
</my-timeline>
<br />
<!-- 管制工夫戳地位与是否暗藏工夫戳 -->
<my-timeline>
<my-timeline-item timestamp="2222-02-02"
> 默认工夫戳在文字上方 </my-timeline-item
>
<my-timeline-item timestamp="3333-03-03" timeLocation="down"
> 通过 timeLocation 属性将工夫戳放在文字下方 </my-timeline-item
>
<my-timeline-item timestamp="4444-04-04" hideTimestamp
> 若不想要工夫戳可应用 hideTimestamp 属性将其暗藏 </my-timeline-item
>
</my-timeline>
</div>
</template>
<script>
export default {data() {
return {
reverse: false,
timeArr: [
{
timestamp: "2022-04-01",
content: "默认工夫线小圆点款式",
},
{
timestamp: "2022-05-01",
content: "更改工夫线小圆点色彩",
borderColor: "red",
},
{
timestamp: "2022-04-01",
content: "应用饿了么的小图标做为工夫线小圆点",
elementIcon: "el-icon-view",
},
{
timestamp: "2022-07-01",
content: "给饿了么的 icon 上色",
elementIcon: "el-icon-location",
iconColor: "green",
},
],
};
},
};
</script>
myTimeline 代码
<script>
export default {
name: "myTimeline",
// 外层组件只承受一个参数即是否反转,内层组件的参数多一些
props: {
reverse: {
// 是否反转,即管制工夫排序形式
type: Boolean,
default: false, // 默认从上往下
},
},
// 应用 render 函数渲染数据
render() {
const reverse = this.reverse;
const classes = {
"my-timeline": true,
"is-reverse": reverse,
};
let slots = this.$slots.default || []; // 获取默认插槽数组
if (reverse) {slots = slots.reverse(); // 默认插槽数组,也是数组,所以也是能够应用 reverse 办法做反转的
}
// 加上动静 class 并传递默认插槽
return <ul class={classes}>{slots}</ul>;
// 整体工夫线构造就是 ul 搭配 li,一个 li 代表一项工夫线
},
};
</script>
<style lang="less">
.my-timeline,
.my-timeline .timeLineItem {list-style: none;}
// 把最初一条竖向工夫线暗藏
.my-timeline .timeLineItem:last-child .verticalLine {display: none;}
</style>
myTimelineItem 代码
<template>
<li class="timeLineItem">
<!-- 垂直方向的线条 -->
<div class="verticalLine"></div>
<!-- 垂直方向的小圆点 -->
<div
class="dots"
:style="{
border: elementIcon
? 'none'
: borderColor
? `2px solid ${borderColor}`
: '2px solid #1890ff',
}"
>
<!-- 上述三元表达式意思:当传了 elementIcon 时,阐明要应用饿了么 UI 的图标,即不应用 border 了,故为 none;当未传 elementIcon 时,再看是否传了 borderColor 了,若传了,就应用传递的 borderColor 作为
border-color 的值,否则就应用默认的 #1890ff 为边框色
-->
<i
v-if="elementIcon"
:style="{color: iconColor}"
:class="elementIcon"
></i>
</div>
<!-- 内容区,通过 flex-direction 管制工夫和细节的高低地位 -->
<div class="content" :class="{isSetTimeDown: timeLocation =='down'}">
<!-- 内容区的工夫 -->
<div class="contentTime" v-if="!hideTimestamp">{{timestamp}}</div>
<!-- 内容区的具体细节 -->
<div class="contentDetail">
<slot></slot>
</div>
</div>
</li>
</template>
<script>
export default {
name: "myTimelineItem",
props: {
// 工夫戳具体值
timestamp: String,
// 是否暗藏工夫戳,只展现文字内容
hideTimestamp: {
type: Boolean,
default: false, // 默认显示工夫戳
},
// 工夫戳的地位,默认工夫戳地位在上方
timeLocation: String,
// 指定工夫线条连贯的小圆点的边框色
borderColor: String,
// 应用饿了么 UI 的图标替换节点小圆点,如 el-icon-more
elementIcon: String,
// 设置饿了么 UI 图标的色彩
iconColor: String,
},
};
</script>
<style scoped lang="less">
.timeLineItem {
position: relative; // 定位管制工夫线和小圆点的地位细节
padding-bottom: 12px;
.verticalLine {
width: 2px;
height: 100%;
background-color: #e9e9e9;
// 定位管制
position: absolute;
top: 4px;
}
.dots {
width: 12px;
height: 12px;
background-color: #fff;
border-radius: 50%;
// 通过定位将小圆点挪动到左侧工夫线上方
position: absolute;
left: -5px;
top: 4px;
i {
position: absolute;
left: -2px;
top: -2px;
}
}
.content {
padding-left: 24px;
display: flex;
// 通过弹性盒方向管制 contentTime 和 contentDetail 的高低地位(默认工夫在上方)
flex-direction: column;
.contentTime {
margin-bottom: 6px;
font-size: 13px;
color: #666;
}
.contentDetail {
margin-bottom: 6px;
font-size: 14px;
color: #333;
}
}
// 是否让工夫在下方,取决于是否 timeLocation 的值是否为 down
.isSetTimeDown {flex-direction: column-reverse;}
}
</style>
如果对您有一点点帮忙的话,欢送 github 不吝 star 哦
^O^