elementui源码学习之仿写一个el-tag

简介: elementui源码学习之仿写一个el-tag
本篇文章记录仿写一个el-divider组件细节,从而有助于大家更好理解饿了么ui对应组件具体工作细节。本文是elementui源码学习仿写系列的又一篇文章,后续空闲了会不断更新并仿写其他组件。源码在github上,大家可以拉下来,npm start运行跑起来,结合注释有助于更好的理解。github仓库地址如下: https://github.com/shuirongshuifu/elementSrcCodeStudy

组件需求分析

关于tag组件,主要是用于展示一些标签信息,一般的需求有如下:

  • tag标签文字颜色自定义
  • tag标签背景色自定义
  • tag标签边框颜色自定义
  • 控制是否展示关闭tag标签小叉号图标
  • 自定义tag标签的文字颜色、背景色、边框颜色
  • 标签的大小类型(大型、中型、小型标签)

饿了么官方使用的是render函数编写的el-tag,所以这里咱们也使用render函数去写。整体来说,这个组件还是比较简单的。注意一下jsx的语法即可。

组件效果图

1.gif

看效果的话,直接复制粘贴运行跑起来,结合注释更有助于理解。最完整的代码在github上哦

使用之代码

<template>
  <div>
    <my-divider lineType="dotted" content-position="left"
      >默认标签样式</my-divider
    >
    <my-tag>默认标签</my-tag>
    <my-tag closable>默认标签可关闭</my-tag>

    <my-divider lineType="dotted" content-position="left"
      >类型标签样式</my-divider
    >
    <my-tag type="primary">类型标签primary</my-tag>
    <my-tag type="primary" closable>类型标签primary可关闭</my-tag>
    <my-tag type="success">类型标签success</my-tag>
    <my-tag type="success" closable>类型标签success可关闭</my-tag>
    <my-tag type="info">类型标签info</my-tag>
    <my-tag type="info" closable>类型标签info可关闭</my-tag>
    <my-tag type="warning">类型标签warning</my-tag>
    <my-tag type="warning" closable>类型标签warning可关闭</my-tag>
    <my-tag type="danger">类型标签danger</my-tag>
    <my-tag type="danger" closable>类型标签danger可关闭</my-tag>

    <my-divider lineType="dotted" content-position="left"
      >自定义标签样式</my-divider
    >
    <my-tag color="blue">标签文字颜色自定义</my-tag>
    <my-tag bgColor="pink">标签背景颜色自定义</my-tag>
    <my-tag borderColor="red">标签边框颜色自定义</my-tag>
    
    <my-divider lineType="dotted" content-position="left"
      >中等标签及大型标签</my-divider
    >
    <my-tag type="primary" sizeType="big" closable>大型标签</my-tag>
    <my-tag type="success" sizeType="medium" closable>中型标签</my-tag>
    <my-tag style="cursor: pointer" type="info" sizeType="small"
      >默认(小型)标签,sizeType="small"写不写都行的</my-tag
    >

    <my-divider lineType="dotted" content-position="left"
      >动态编辑标签</my-divider
    >
    <my-tag
      v-for="(item, index) in arr"
      closable
      @close="handleClose(item)"
      @click="handleClick(item)"
      type="success"
      :key="item"
      >{{ item }}</my-tag
    >
    <el-input
      v-model.trim="val"
      @blur="blurFn"
      size="mini"
      style="width: 120px"
    ></el-input>
  </div>
</template>

<script>
export default {
  data() {
    return {
      arr: ["标签一", "标签二", "标签三"],
      val: "",
    };
  },
  methods: {
    blurFn() {
      if (this.val === "") return;
      this.arr.push(this.val);
      this.val = "";
    },
    handleClose(tag) {
      // 找到点击的是哪个
      let i = this.arr.findIndex((item) => {
        return tag === item;
      });
      // 删除之
      this.arr.splice(i, 1);
    },
    handleClick(tag) {
      console.log("点击标签啦", tag);
    },
  },
};
</script>

封装组件的代码

<script>
const typeArr = ["primary", "success", "info", "warning", "danger"]; // 标签类型数组
const sizeType = ["big", "medium", "small"]; // 标签大小数组
export default {
  name: "myTag",
  props: {
    closable: Boolean, // 是否展示可关闭的小叉号图标
    color: String, // 标签文字的颜色
    bgColor: String, // 标签背景色
    borderColor: String, // 标签边框颜色
    // 五种标签类型
    type: {
      type: String,
      validator(val) {
        return typeArr.includes(val); // 校验类型
      },
    },
    // 三种标签大小
    sizeType: {
      type: String,
      validator(val) {
        return sizeType.includes(val); // 校验大小
      },
    },
  },
  methods: {
    handleClose(event) {
      /* 阻止冒泡防止与下方的handleClick方法冲突,要不然点击close关闭小图标,也会
         触发下方click事件的执行。即:内层事件阻止冒泡与外层事件隔离开来 */
      event.stopPropagation();
      this.$emit("close", event);
    },
    handleClick(event) {
      this.$emit("click", event);
    },
  },
  // render函数jsx语法更加灵活
  render(h) {
    // 1. 准备样式类 class绑定classArr数组常用样式,style绑定props变量自定义样式
    const classArr = ["my-tag", this.type, this.sizeType];
    // 2. 准备一个dom,并绑定相关class、style、event
    const tagEl = (
      <span
        class={classArr}
        style={{
          backgroundColor: this.bgColor,
          color: this.color,
          borderColor: this.borderColor,
        }}
        on-click={this.handleClick}
      >
        {/* 默认插槽渲染内容即my-tag标签中的文字 */}
        {this.$slots.default}
        {/* 三元表达式条件控制是否渲染关闭小图标 */}
        {this.closable ? (
          <span class="close-tag" on-click={this.handleClose}>
            x
          </span>
        ) : null}
      </span>
    );
    // 3. 返回render渲染之
    return <transition name="el-fade-in">{tagEl}</transition>;
    // 使用饿了么UI自带的渐变过渡动画
  },
};
</script>
<style scoped>
/* 默认标签样式 */
.my-tag {
  display: inline-block;
  box-sizing: border-box;
  padding: 0 8px;
  color: #252525;
  background-color: #fafafa;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  font-size: 12px;
  white-space: nowrap;
  height: auto;
  line-height: 20px;
  margin: 0 8px 8px 0;
}
/* 标签关闭小叉号样式 */
.close-tag {
  position: relative;
  margin-left: 5px;
  cursor: pointer;
  display: inline-block;
  transform: translateY(-6%);
}
/* 5种类型标签样式 */
.primary {
  color: #409eff;
  border: 1px solid #d9ecff;
  background-color: #ecf5ff;
}
.success {
  background-color: #f0f9eb;
  border-color: #e1f3d8;
  color: #67c23a;
}
.info {
  background-color: #f4f4f5;
  border-color: #e9e9eb;
  color: #909399;
}
.warning {
  background-color: #fdf6ec;
  border-color: #faecd8;
  color: #e6a23c;
}
.danger {
  background-color: #fef0f0;
  border-color: #fde2e2;
  color: #f56c6c;
}
/* 默认小型标签样式,可选值为中等标签、大型标签。当然这里没有small,因为small就是默认的 */
.big {
  padding: 4px 10px;
}
.medium {
  padding: 2px 10px;
}
</style>

总结

  • 大家封装自己的组件的时候,最好借鉴其他UI组件库,比如这里仿写el-tag也是参照了antD的设计方式。
  • 再一个就是仿写组件,不是把官方的组件全部照搬过来,而是适当取舍,保留比较常用的组件功能,暂时摒弃冷门组件功能,并加入自己公司常用的功能,以及自己的理解
  • 如果有遇到冷门的组件功能,可以考虑再单独封装一个组件去解决
  • 组件需要集成一些功能,但是不能集成非常多的功能,高内聚
  • 本人水平有限,说的不一定对,仅供各位道友参考 ^_^
相关文章
|
12月前
|
存储 缓存 固态存储
系统分区完全指南:多种方法实现专业磁盘管理
合理磁盘分区可提升搜索效率、增强容错性、优化性能并便于管理。建议分为系统盘与数据盘,Windows推荐GPT格式,支持更大容量与UEFI启动。可通过系统自带工具或DiskGenius进行分区操作,注意备份、4K对齐及电源稳定。
2419 3
|
NoSQL Redis 数据安全/隐私保护
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
文章提供了Redis最流行的图形化界面工具Another Redis Desktop Manager的下载及使用教程,包括如何下载、解压、连接Redis服务器以及使用控制台和查看数据类型详细信息。
7091 6
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
|
人工智能 数据可视化 数据库连接
保姆级教程 | 0代码,用n8n一键打通微信、钉钉与数据库,效率提升500%
n8n是一款开源可视化自动化工具,无需编程即可连接微信、钉钉、数据库等400+服务。通过拖拽节点搭建工作流,实现数据同步、消息通知等自动化,效率提升500%。支持免费私有部署,安全可控,零成本开启高效办公新体验。
|
监控 物联网 大数据
应急物资智能仓储系统解决方案
凌讯应急物资智能仓储系统集成了物联网、云计算、大数据等技术,实现了物资实时监控、精准定位和智能调度。通过RFID、二维码等自动识别技术,确保信息准确更新,支持移动端操作,快速响应突发事件,提供定制化解决方案,优化跨部门协作,提高救援效率,降低风险。
723 47
|
数据采集 存储 移动开发
关于数据埋点的认识以及在流量分析系统中的实际使用
关于数据埋点的认识以及在流量分析系统中的实际使用
1916 0
关于数据埋点的认识以及在流量分析系统中的实际使用
|
数据可视化 PyTorch Serverless
Python 性能分析的几个方法,找到你代码中的那个她
我们在编写了一个脚本在笔记本上处理一些数据,然后去喝杯咖啡或者上了个厕所,15分钟后回来时发现进度才完成不到10%。 我们的脑袋里面就会发问:为什么这么慢?究竟是在哪个部分是慢的?是读取数据、处理数据还是保存数据?如何让它变快?它真的很慢吗? 有了这个疑问我们尝试去解决这个问题,下面我们介绍几个 python 性能分析的工具。
|
机器学习/深度学习 数据采集 大数据
|
关系型数据库 MySQL
MySQL 的 union 和union all 的区别
【5月更文挑战第4天】MySQL 的 union 和union all 的区别
1337 7
|
前端开发 Java 开发工具
如何在Spring Boot框架下实现高效的Excel服务端导入导出?
ArtifactId:是项目的唯一标识符,在实际开发中一般对应项目的名称,就是项目根目录的名称。 Group Id,Artfact Id是保证项目唯一性的标识,一般来说如果项目打包上传至maven这样的包管理仓库中。在搜索你的项目时,Group Id,Artfact Id是必要的条件。 Version:版本号,默认0.0.1-SNAPSHOT。SNAPSHOT代表不稳定的版本,与之相对的有RELEASE。 Project type:工程的类型,maven工程还是gradle工程。 Language:语言(Java,Kotlin,Groovy)。
511 0