1
This article records and imitates a el-timeline component details, which will help you better understand the specific working details of the corresponding components of the Ele.me ui. This article is another article in the elementui source code learning and imitation series. I will continue to update and imitate other components when I am free. The source code is on github, you can pull it down, npm start to run, and comments are helpful for better understanding. The github warehouse address is as follows: github.com/shuirongshu…

Component Analysis

component parts

The timeline component components can be divided into four parts:

  • timeline dots
  • timeline vertical line
  • timestamp
  • Specific content details

As shown below:

Therefore, the requirements for the timeline component are mainly controlled from these four perspectives. The general timeline component requirements are as follows:

Component requirements analysis

Regarding the components of the dividing line, the commonly used scene requirements are:

  • For example, the display according to the timeline or in reverse order (such as: log records)
  • For example, the style color of the default timeline dots, and the color can be customized (the default blue circle here)
  • For example, you can also use small icons to replace the small dots on the timeline (for example, use the Ele.me icon)
  • Use the small icon of Ele.me, and sometimes you need to color the icon
  • For example, control the location of timestamps and specific content details (here the default timestamp is above, and sometimes the timestamp may be below)
  • Sometimes, you may not need to display the timestamp, but only the content, so you need to add a variable to hide the timestamp

Personal opinion on official components:

1. The official components provide and inject can be removed, as shown below:

2. The official component uses two copies to control the timestamp position dom , which can be changed to one copy dom with the flex box direction control

3. Refer to the parties to make a copy of the package component 简约的处理

You can take a look at the timeline components of antd and iview. The parameters are indeed less than the timeline components of Ele.me.

antd: https://ant.design/components/timeline-cn/

iview: https://www.iviewui.com/view-ui-plus/component/view/timeline

Personal opinion is not necessarily correct, for reference only

Review knowledge points in components

Learn from the past

this.$slots.default.reverse()

The default slot array this.$slots.default is also an array, so the array method can also be used.

Here, the positive sequence flashback that controls the timeline is used. This method

Write quaternary expressions in :style

Colon style can actually write ternary, or quaternary or more, expressions containing variables, as follows:

 <div
      class="dots"
      :style="{
        border: elementIcon
          ? 'none'
          : borderColor
          ? `2px solid ${borderColor}`
          : '2px solid #1890ff',
      }"
    >
</div>

大意: :styleclass dotsdom元素设置---0306058755aee0f4fb70627738c03d38---边框样式,具体边框border in elementIcon and borderColor the value of these two variables.

code

For demonstration, just copy and paste it to use. Of course the complete code is on github ^_^

Let's take a look at the renderings first, then look at the code

renderings

Use component code

 <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 code

 <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 code

 <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>
If you have a little help, welcome to github and star ^O^

水冗水孚
1.1k 声望585 粉丝

每一个不曾起舞的日子,都是对生命的辜负