关于前端:Element-2-组件源码剖析之Timeline-时间轴

7次阅读

共计 4633 个字符,预计需要花费 12 分钟才能阅读完成。

简介

时间轴组件Timeline 罕用于垂直展现的工夫流信息。当有一系列信息需按工夫排列时,应用时间轴进行视觉上的(正序或倒序)串联。本文将剖析其源码实现,急躁读完,置信会对您有所帮忙。🔗 组件文档 Timeline 🔗 gitee 源码

更多组件分析详见 👉 📚 Element 2 源码分析组件总览

组件源码

时间轴性能提供了两个组件:el-timelineel-timeline-item

各组件的 prop 申明,各属性性能阐明详见官网文档 Timeline#attributes。

根组件 main.vue

根组件是一个函数式组件,应用渲染函数 /JSX 语法一个无序列表<ul> 元素。提供匿名插槽展现节点内容。

// packages\timeline\src\main.vue
<script>
  export default {
    name: 'ElTimeline',
    props: {
      reverse: {
        type: Boolean,
        default: false
      }
    },
    // dead code
    provide() {
      return {timeline: this};
    },
    // 渲染函数
    render() {
      const reverse = this.reverse;
      const classes = {
        'el-timeline': true,
        'is-reverse': reverse
      };
      let slots = this.$slots.default || [];
      if (reverse) {slots = slots.reverse();
      }
      return (<ul class={ classes}>
        {slots}
      </ul>);
    }
  };
</script> 

属性 reverse 用于节点排序方向。通过 this.$slots 拜访传入插槽的 元素类型为 vnode 节点数组,而后应用 办法 reverse() 将数组中元素的地位颠倒。

let slots = this.$slots.default || [];
if (reverse) {slots = slots.reverse();
}

此排序是元素节点地位程序,不是节点内工夫戳排序。

代码中存在不少 dead code, 具体性能意义不明(感觉性能开发一半就停了)。

属性 reverse值为 ture, 节点逆序时生成类名is-reverse,然而样式表中未定义此类。

const classes = {'is-reverse': reverse};

// packages\theme-chalk\src\timeline.scss
@include b(timeline) {
  margin: 0;
  font-size: $--font-size-base;
  list-style: none;
  // 暗藏末节点轴线
  & .el-timeline-item:last-child {
    & .el-timeline-item__tail {display: none;}
  }
}

依赖注入代码即便正文掉也不影响组件性能。

// packages\timeline\src\main.vue 
provide() {
  return {timeline: this};
},

// packages\timeline\src\item.vue
inject: ['timeline'],

节点组件 item.vue

节点组件的模板用于渲染一个示意列表里的条目标<li> 元素。该元素节点下内容蕴含三局部:

  • 垂直方向轴线。
  • 节点 / 图标。
  • 内容(含工夫戳)。
<template>
  <li class="el-timeline-item">
    <!-- 轴线 -->
    <div class="el-timeline-item__tail"></div>
    <!-- 节点 / 图标 -->
    <div v-if="!$slots.dot" class="el-timeline-item__node" >
      // 图标
    </div>
    <div v-if="$slots.dot" class="el-timeline-item__dot">
      <slot name="dot"></slot>
    </div>
    <!-- 信息内容 -->
    <div class="el-timeline-item__wrapper">
      // 内容
    </div>
  </li>
</template>  

渲染成果如下:

上一大节中介绍了根组件定义了款式用于设置末节点元素的轴线不显示。

.el-timeline .el-timeline-item:last-child .el-timeline-item__tail {display: none;}

轴线

类名 el-timeline-item__tail 的 div 元素应用相对布局,在节点元素外部居左 left: 4px,并通过定义border-left height 款式属性来实现垂直轴线成果。

.el-timeline-item__tail {
  position: absolute;
  left: 4px;
  height: 100%;
  border-left: 2px solid #e4e7ed;
}

节点

时间轴节点默为圆形实心点,色彩#e4e7ed

  • 属性 type 用于设置节点类型主题,生成不同色彩款式类el-timeline-item__node--[primary/success/warning/danger/info]
  • 属性size 用于设置预设节点尺寸(蕴含偏移量),生成el-timeline-item__node--[normal/large]
  • 属性 color 用于元素的内联款式 backgroundColor: color,设置节点色彩。
  • 设置属性 icon值传入 icon 类名就可间接间接使⽤图标。
  • 提供了具名 dot 插槽用于自定义节点。
  • <!-- 实心圆点 / 图标 -->
    <div v-if="!$slots.dot"
    class="el-timeline-item__node"
    :class="[`el-timeline-item__node--${size || ''}`,
      `el-timeline-item__node--${type || ''}`
    ]":style="{backgroundColor: color}"
    >
    <i v-if="icon"
      class="el-timeline-item__icon"
      :class="icon"
    ></i>
    </div>
    <!-- 自定义 -->
    <div v-if="$slots.dot" class="el-timeline-item__dot">
    <slot name="dot"></slot>
    </div>

时间轴节点也是采纳相对布局,元素的尺寸和布局偏移在款式类 el-timeline-item__node--normalel-timeline-item__node--large定义。

.el-timeline-item__node {
  position: absolute;
  background-color: #e4e7ed;
  border-radius: 50%; 
}
// 尺寸及布局偏移
.el-timeline-item__node--normal {
  left: -1px;
  width: 12px;
  height: 12px;
}
.el-timeline-item__node--large {
  left: -2px;
  width: 14px;
  height: 14px;
}

信息内容

时间轴内容蕴含工夫戳和信息,通过属性 placement 可设置工夫戳地位 top / bottom

信息内容应用匿名插槽渲染。工夫戳地位没有应用相对布局或 flex 布局。当设置值 top 时,工夫戳内容在信息内容之前;设置值 bottom 时,信息内容就会在工夫戳内容之前。浏览器渲染时会恪守 html 排列程序。

<!-- 时间轴内容 -->
<div class="el-timeline-item__wrapper">
  <!-- 工夫戳地位 top-->
  <div v-if="!hideTimestamp && placement ==='top'"class="el-timeline-item__timestamp is-top">
    {{timestamp}}
  </div>
  <!-- 内容 -->
  <div class="el-timeline-item__content">
    <slot></slot>
  </div>
  <!-- 工夫戳地位 bottom-->
  <div v-if="!hideTimestamp && placement ==='bottom'"class="el-timeline-item__timestamp is-bottom">
    {{timestamp}}
  </div>
</div>

款式实现

组件款式源码 packages\theme-chalk\src\timeline.scsspackages\theme-chalk\src\timeline-item.scss应用混合指令嵌套生成组件款式。

// packages\theme-chalk\src\timeline.scss
// 生成 .el-timeline
@include b(timeline) {
  // ...
  
  // .el-timeline .el-timeline-item:last-child .el-timeline-item__tail
  & .el-timeline-item:last-child {
    & .el-timeline-item__tail {// ...}
  }
} 


// packages\theme-chalk\src\timeline-item.scss
// 生成 .el-timeline-item 
@include b(timeline-item) {
  // ... 

  // 生成  .el-timeline-item__wrapper
  @include e(wrapper) {// ...}
  // 生成 .el-timeline-item__tail
  @include e(tail) {// ...}
  // 生成 .el-timeline-item__icon
  @include e(icon) {// ...}
  // 生成 .el-timeline-item__node
  @include e(node) {
    // ...
    // 生成 .el-timeline-item__node--normal
    @include m(normal) {// ...}
    // 生成  .el-timeline-item__node--large   
    @include m(large) {// ...}
    // 生成 .el-timeline-item__node--[primary/success/warning/danger/info]
    @include m(primary) {// ...} 
    // success/warning/danger/info ....
    
  }
  // 生成 .el-timeline-item__dot
  @include e(dot) {// ...}
  // 生成 .el-timeline-item__content 
  @include e(content) {// ...}
  // 生成 .el-timeline-item__timestamp
  @include e(timestamp) {
    // ...
    // 生成 .el-timeline-item__timestamp.is-top 
    @include when(top) {// ...}
    // 生成 .el-timeline-item__timestamp.is-bottom
    @include when(bottom) {// ...}
  }
}

关注专栏

如果本文对您有所帮忙请关注➕、点赞👍、珍藏⭐!您的认可就是对我的最大反对!

正文完
 0