3.14 Empty 空状态

0x00 简介

组件 Empty 用于空状态时的展示占位图。 使用场景多为当目前没有数据时,用于显式的用户提示; 或初始化场景时的引导创建流程。 本文将深入分析源码,剖析其实现原理,耐心读完,相信会对您有所帮助。组件源码实现详见packages\empty\src\index.vue 。 🔗 组件文档 Empty 🔗 gitee源码 index.vue

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

0x01 组件源码

template 模板内容

index.vue 组件模板创建一个class名为el-empty<div> 元素根节点,包含三个子节点 空状态图片描述文字底部内容

每个节点都提供了插槽,需要注意的底部内容的插槽为匿名插槽,分发内容时需要指明 slot#name,否则内容都默认分发至 底部内容 节点内。。

<template>
  <div class="el-empty">
    <!-- 空状态图片 slot image -->
    <div class="el-empty__image" :style="imageStyle">
      <img v-if="image" :src="image" ondragstart="return false">
      <slot v-else name="image">
        <img-empty />
      </slot>
    </div>
    <!-- 描述文字 slot  description -->
    <div class="el-empty__description">
      <slot v-if="$slots.description" name="description"></slot>
      <p v-else>{{ emptyDescription }}</p>
    </div>
    <!-- 底部内容 匿名插槽-->
    <div v-if="$slots.default" class="el-empty__bottom">
      <slot></slot>
    </div>
  </div>
</template>

空状态图片

该节点是一个class 名为el-empty__image<div> 元素,使用计算属性 imageStyle 定义图片宽度。

若设置 image 属性传入图片 URL,优先渲染 <img> 元素,图片不支持拖放 ondragstart="return false"

默认渲染image插槽的后背内容--内置的SVG图标组件 <img-empty/>,组件详情详见下文章节 内置 svg 图标组件

// 组件引入
import ImgEmpty from './img-empty.vue'; 

export default {
  name: 'ElEmpty',
  components: {
    // name: 'ImgEmpty',
    [ImgEmpty.name]: ImgEmpty
  },
}

描述文字

该节点是一个class 名为el-empty__description<div> 元素,提供了名为description的具名slot

默认使用 <p> 段落元素包裹计算属性 emptyDescription渲染。 只有当向description插槽分发内容时 v-if="$slots.description",使用插槽渲染内容。

计算属性 emptyDescription 返回 prop 的 description属性值 或 国际化空状态描述设置 t('el.empty.description')。优先返回 description 值。

底部内容

该节点是一个class 名为el-empty__bottom<div> 元素,提供了匿名插槽。只有向该插槽分发内容时v-if="$slots.default",该节点才会被渲染。

attributes 属性

组件定义了3 个prop : imageimageSizedescription

props: {
  // 图片URL
  image: {
    type: String,
    default: ''
  },
  // 设定图片宽度
  imageSize: Number,
  // 文本描述
  description: {
    type: String,
    default: ''
  }
},

计算属性

emptyDescription

description 属性值是 truthy 时,返回description 属性值。否则默认返回国际化空状态描述设置 t('el.empty.description')

// 引入国际化处理方法
import { t } from 'element-ui/src/locale';

emptyDescription() {
  return this.description || t('el.empty.description');
},

前文 组件源码国际化 提到国际化功能也可以通过 mixin 方式提供给组件页面使用。

import Locale from 'element-ui/src/mixins/locale';

export default {
  mixins: [Locale], 
  computed: {
    emptyDescription() {
      // return this.description || t('el.empty.description');
      return this.description || this.t('el.empty.description');
    }, 
  }
};

imageStyle

定义图片显示尺寸(宽度)。当 imageSize 属性值是 truthy 时,返回自定义宽度样式。

imageStyle() {
  return {
    width: this.imageSize ? `${this.imageSize}px` : ''
  };
}

内置 svg 图标组件

img-empty.vue图标组件封装一个 <svg>元素, 图片内容如下 👇


0x02 组件样式

src/empty.scss

组件样式源码 packages\theme-chalk\src\empty.scss 使用混合指令 be 嵌套生成组件样式。

// 生成 .el-empty
@include b(empty) {
  // ...

  // 生成 .el-empty__image
  @include e(image) {
    // ...
    
    // 生成 .el-empty__image img 
    img {
      // ...
    }
    
    // 生成 .el-empty__image svg
    svg {
      // ...
    }
  }
  
  // 生成 .el-empty__description
  @include e(description) {
    // ...
    
    // 生成 .el-empty__description p
    p {
      // ...
    }
  }
  
  // 生成 .el-empty__bottom
  @include e(bottom) {
    // ...
  }
}

lib/empty.scss

前文可知使用 gulpfile.js编译 scss 文件转换为CSS,经过浏览器兼容、格式压缩,最后生成 packages\theme-chalk\lib\empty.scss,内容格式如下。

.el-empty { /* ...  */ }
/* image */
.el-empty__image { /* ...  */ }
.el-empty__image img, .el-empty__image svg { /* ...  */ }
.el-empty__image img { /* ...  */ }
.el-empty__image svg { /* ...  */ }
/* description */
.el-empty__description { /* ...  */ }
.el-empty__description p { /* ...  */ }
/* bottom  */
.el-empty__bottom { /* ...  */ } 

最后更新于