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

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

组件需求分析

关于分割线的组件,一般使用的场景有:

  • 分割线之水平分割(如:段落与段落之间分隔)
  • 水平分割线加上文字描述(文字描述位置一般是位于分割线的左侧、居中、右侧)
  • 分割类型之垂直分割(横向的行内文字与文字之间的分割)
  • 分割线样式类型(solid分割线或dashed分割线或dotted分割线)
因为垂直分割距离不够,所以垂直分割没有文字描述

组件中用到的知识点

函数式组件

我们知道,一个函数,其实就是一个加工流水线,我们入参,经过函数的加工以后,得到return加工后的结果。

对于组件而言,其实也可以当做一个函数(函数式组件),我们传递参数,组件props接收,然后组件再根据传参的不同,渲染出对应的样式效果。

这种方式和原来的我们使用组件的方式其实差不多,只不过更加精简,毕竟只考虑接收参数,没有生命周期、this实例之类的。所以函数式组件的渲染效率会比普通组件高。

所以有些情况下,使用函数式组件效率会更高

函数式组件的两种定义方式

比如,通过传参方式去渲染文字,可以有以下两种方式

方式一:render函数定义

<script>
export default {
  functional: true, // 一定要指明是函数式组件
  props: {
    bookName: {
      type: String,
      default: "斗破苍穹",
    },
  },
  // context上下文,有点像this的意思。但不一样
  render: function (createElement, context) {
    // 创建一个h3标签,标签内容是上下文对象中的props中的bookName字段  
    return createElement("h3", {}, context.props.bookName);
  },
};
</script>

方式二:template定义

<!-- 模板标签上加上functional关键字表明是函数式组件 -->
<template functional>
  <div>
    <h3>{{ props.bookName }}</h3>
  </div>
</template>

<script>
  export default {
    props: {
      bookName: {
        type: String,
        default: "斗破苍穹",
      },
    },
  }
</script>
关于函数式组件的具体细节,详情见官方文档: https://cn.vuejs.org/v2/guide/render-function.html#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6

这里为什么要提到函数式组件呢?因为el-divider组件就是使用函数式组件进行封装的(因为组件只是做分割线条的展示,所以不需要有this实例,生命周期之类的)

故:为了提升渲染效率,这里使用函数式组件

使用函数式组件的情况大致有以下:

  • 只做展示的组件,毕竟没啥逻辑操作相关
  • 高阶组件的操作
  • 循环中也可以考虑使用
  • 整体来说,函数式组件还是比较灵活的

解决一像素太粗的问题

先看一下问题图

1.png

只需要给对应dom元素稍微缩放一下即可:

transform: scaleY(0.95); 或 transform: scaleX(0.95);

组件封装

el-divider组件整体还是比较简单的,主要是函数式组件的参数使用细节

组件封装的效果图

2.png

组件封装的代码

使用的代码

<template>
  <div class="wrap">
    <h3>实线solid靠左</h3>
    <my-divider class="staticClass_must_hava" content-position="left"
      >早上好</my-divider
    >
    <h3>实线solid居中</h3>
    <my-divider content-position="center">中午好</my-divider>
    <h3>实线solid靠右</h3>
    <my-divider content-position="right">下午好</my-divider>
    <h3>虚线dashed靠左</h3>
    <my-divider lineType="dashed" content-position="left">早上好</my-divider>
    <h3>虚线dashed居中</h3>
    <my-divider lineType="dashed" content-position="center">中午好</my-divider>
    <h3>虚线dashed靠右</h3>
    <my-divider lineType="dashed" content-position="right">下午好</my-divider>
    <h3>圆点dotted靠左</h3>
    <my-divider lineType="dotted" content-position="left">早上好</my-divider>
    <h3>圆点dotted居中</h3>
    <my-divider lineType="dotted" content-position="center">中午好</my-divider>
    <h3>圆点dotted靠右</h3>
    <my-divider lineType="dotted" content-position="right">下午好</my-divider>
    <h3>竖向分割线</h3>
    <span>早上好</span>
    <my-divider direction="vertical"></my-divider>
    <span>中午好</span>
    <my-divider direction="vertical"></my-divider>
    <span>下午好</span>
  </div>
</template>

<script>
import myDivider from "./myDivider.vue";
export default {
  components: { myDivider },
};
</script>

<style>
.wrap { padding: 24px; }
.staticClass_must_hava { border-bottom: 1px solid #baf !important; }
</style>

封装的代码

<template functional>
  <!-- functional关键字加上后,即代表为函数式组件,就没有生命周期、this实例等了,故渲染更快,性能更高 -->
  <!-- v-bind和v-on这里不加也行。毕竟函数式组件个人愚见简洁建议一些,attrs存放传递来的数据,listeners传递任何事件监听器 -->
  <!-- data.staticClass需要加上,否则外层给组件加的class属性在审查元素的时候不会出现的,相当于没加   -->
  <div
    v-bind="data.attrs"
    v-on="listeners"
    :class="[data.staticClass, `${props.direction}`, `${props.lineType}`]"
  >
    <!-- 当分割线为水平的时候,且插槽有内容的时候,才渲染对应数据 -->
    <!-- slots()方法返回插槽数据对象,default为默认插槽;相当于this.$slots.default。本系列文章中仿写一个el-tabs 也提到了此知识点  -->
    <div
      v-if="props.direction === 'horizontal' && slots().default"
      :class="['text', `${props.contentPosition}`]"
    >
      <slot />
    </div>
  </div>
</template>

<script>
export default {
  name: "myDivider",
  props: {
    // 分割线的方向,默认水平horizontal(垂直vertical可选)
    direction: {
      type: String,
      default: "horizontal",
      validator(val) {
        return ["horizontal", "vertical"].includes(val);
      },
    },
    // 文本内容位置,默认居中(仅当分割线为水平方向时,才渲染对应内容)
    contentPosition: {
      type: String,
      default: "center",
      validator(val) {
        return ["left", "center", "right"].includes(val);
      },
    },
    // 分割线线条类型,默认实线,可选虚线,圆点线
    lineType: {
      type: String,
      default: "solid",
      validator(val) {
        return ["solid", "dashed", "dotted"].includes(val);
      },
    },
  },
};
</script>
<style lang="less" scoped>
// 水平样式
.horizontal {
  width: 100%;
  border-bottom: 1px solid #333; // 默认solid分割线样式
  display: block;
  margin: 12px 0;
  position: relative;
  // 缩放0.95倍可以解决一像素问题(一像素看着比实际粗)横线Y缩放
  transform: scaleY(0.95);
}
// dashed分割线
.dashed {
  border-bottom: 1px dashed #333;
}
// dotted分割线
.dotted {
  border-bottom: 1px dotted #333;
}
// 垂直样式
.vertical {
  display: inline-block;
  width: 1px;
  height: 1em;
  margin: 0 8px;
  background-color: #333;
  vertical-align: middle;
  position: relative;
  top: -1px; // 微调一下位置
  // 缩放0.95倍可以解决一像素问题(一像素看着比实际粗)竖线X缩放
  transform: scaleX(0.95);
}
// 文本样式
.text {
  position: absolute;
  padding: 0 12px;
  color: #333;
  font-size: 14px;
  transform: translateY(-50%); // y轴移动自身的一半,使其垂直方向居中
  background-color: #fff; // 通过背景色和padding去盖住水平分割线条
}
// 文本靠左
.text.left {
  left: 36px;
}
// 文本靠右
.text.right {
  right: 36px;
}
// 文本居中
.text.center {
  left: 50%;
  // 居中的话,别忘了要回正。即XY轴方向都平移自身的一半
  transform: translateX(-50%) translateY(-50%);
}
</style>
相关文章
|
Linux Python Windows
为Python打包创建一个世外桃源,解决打包太大且启动慢的问题
首先是我用的是Anaconda的集成环境,由于Anaconda或者自己搭建的环境里内置了很多库,而且在日常的开发中又安装很多开发所需要的其他库,打包的时候就把很多不必要的模块打包进去,导致打包出来的文件过于臃肿.打开慢由于运行需要加载这些环境,由于加载的库过多导致耗时过长,而且Python是一门解释型语言,本身运行效率上也稍慢,所以能够明显体会到启动时的漫长等待 我们写代码就是为了高效,怎么能受得了打开慢且占资源的东西呢,那如何能解决这个问题呢?
2942 1
|
消息中间件 Kafka 流计算
Flink读取Kafka报Error sending fetch request
实时计算Flink读取消息队列Kafka,flink日志中出现Error sending fetch request (sessionId=1510763375, epoch=12890978) to node 103: {}. org.apache.flink.kafka.shaded.org.apache.kafka.common.errors.DisconnectException: null
13698 3
Flink读取Kafka报Error sending fetch request
|
数据采集 存储 Web App开发
Python爬虫技巧:设置Cookie永不超时的详细指南
Python爬虫技巧:设置Cookie永不超时的详细指南
|
算法 API 开发者
沪深A股实时行情API接入指南
逐笔Tick数据接口,查询A股上市公司的最新成交明细,确保获取市场的最新交易信息。返回示例如下:
|
人工智能
《AI助力生物学:基因编辑与蛋白质结构解析的加速引擎》
在生物学研究中,AI正发挥重要作用,特别是在基因编辑和蛋白质结构解析方面。AI通过设计新型基因编辑工具(如OpenCRISPR™)、提高编辑效率与精准度(如EVOLVEpro),以及优化整个编辑过程,显著加速了基因编辑的研究进展。在蛋白质结构解析领域,AI技术如AlphaFold实现了精准预测蛋白质三维结构,加速了蛋白质设计与改造,并解析蛋白质相互作用网络。这不仅推动了医学和农业领域的发展,也带来了伦理和法律等挑战,需要确保其健康、可持续发展。
753 11
|
JavaScript 前端开发 数据可视化
20.6K star!Excel级交互体验!这款开源Web表格神器绝了!
Handsontable 是一款功能强大的 JavaScript 数据表格组件,提供类 Excel 的交互体验。支持实时协作、数据绑定、公式计算等企业级功能,可轻松集成到 React/Vue/Angular 等主流框架。
3320 11
|
域名解析 人工智能 缓存
无前端经验如何快速搭建游戏站:使用 windsurf 从零到上线的详细指南
本指南涵盖游戏站页面初稿设计、工具配置、内容设计与功能实现及部署上线的全流程。通过参考优秀网站设计,利用v0.dev平台完成页面布局和样式调整,并下载代码进行后续开发。使用Windsurf配置工作空间规则,确保以用户易懂的方式推进项目。逐步实现多语言支持、favicon设置、嵌入游戏等功能,确保网页专业且用户体验良好。最后通过购买域名、GitHub托管代码、Vercel部署等步骤将游戏站成功上线。
1046 10
|
容灾 网络协议 数据库
云卓越架构:云上网络稳定性建设和应用稳定性治理最佳实践
本文介绍了云上网络稳定性体系建设的关键内容,包括面向失败的架构设计、可观测性与应急恢复、客户案例及阿里巴巴的核心电商架构演进。首先强调了网络稳定性的挑战及其应对策略,如责任共担模型和冗余设计。接着详细探讨了多可用区部署、弹性架构规划及跨地域容灾设计的最佳实践,特别是阿里云的产品和技术如何助力实现高可用性和快速故障恢复。最后通过具体案例展示了秒级故障转移的效果,以及同城多活架构下的实际应用。这些措施共同确保了业务在面对网络故障时的持续稳定运行。
|
编解码 人工智能 缓存
轻装出海:一站式微短剧出海指南
轻装出海:一站式微短剧出海指南
1436 0
|
关系型数据库 MySQL 大数据
DataX:数据同步的超音速英雄!阿里开源工具带你飞越数据传输的银河系,告别等待和故障的恐惧!快来见证这一数据工程的奇迹!
【8月更文挑战第13天】DataX是由阿里巴巴开源的一款专为大规模数据同步设计的工具,在数据工程领域展现强大竞争力。它采用插件化架构,支持多种数据源间的高效迁移。相较于Apache Sqoop和Flume,DataX通过并发写入和流处理实现了高性能同步,并简化了配置流程。DataX还支持故障恢复,能够在同步中断后继续执行,节省时间和资源。这些特性使其成为构建高效可靠数据同步方案的理想选择。
2422 2