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

目录
  • 正文
  • 组件需求分析
  • 组件中用到的知识点
    • 函数式组件
    • 函数式组件的两种定义方式
    • 解决一像素太粗的问题
  • 组件封装
    • 组件封装的效果图
    • 组件封装的代码

正文

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

github仓库地址如下:github.com/shuirongshu…

组件需求分析

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

  • 分割线之水平分割(如:段落与段落之间分隔)
  • 水平分割线加上文字描述(文字描述位置一般是位于分割线的左侧、居中、右侧)
  • 分割类型之垂直分割(横向的行内文字与文字之间的分割)
  • 分割线样式类型(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>

关于函数式组件的具体细节,详情见官方文档:cn.vuejs.org/v2/guide/re…

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

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

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

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

解决一像素太粗的问题

先看一下问题图

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

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

组件封装

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

组件封装的效果图

组件封装的代码

使用的代码

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

以上就是elementui源码学习之仿写一个el-divider组件的详细内容,更多关于elementui仿写el-divider的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue递归组件实现elementUI多级菜单

    本文实例为大家分享了vue递归组件实现elementUI多级菜单的具体代码,供大家参考,具体内容如下 先看效果: 一.子组件 <template>     <div class="myDiv">         <!-- 这里的listAll用于接收父组件传递进来的菜单列表 -->         <template v-for="(item,i) in listAll">             <!-- 有c

  • vue+elementui实现动态添加行/可编辑的table

    本文实例为大家分享了vue+elementui实现动态添加行.可编辑的table的具体代码,供大家参考,具体内容如下 HTMl代码块: <el-col :span="24">     <el-form-item label="与承租户同户籍成员:" :label-width="formLabelWidth">         <el-table :data="zichandetail.members&quo

  • VUE-ElementUI 时间区间选择器的使用

    目录 VUE-ElementUI 时间区间选择器 一.单个输入框 二.两个输入框 elementUI-日期选择器(两个框 限制选择范围.快捷键选择) 两个日期框选择 VUE-ElementUI 时间区间选择器 官方文档中使用picker-options属性来限制可选择的日期 一.单个输入框 <el-date-picker        v-model="value1"        type="date"        placeholder="选择

  • elementui下image组件的使用

    目录 elementui-image组件的组成 elementui-image组件的功能 elementui-image的功能实现 fit的样式实现 图片懒加载的实现方式 图片加载失败和加载中的可配置的实现 图片预览的功能模块实现(image-view.vue文件) 关于elementui管理事件的一些解读 总结 elementui-image组件的组成 elementui的image模块主要是有main.vue,image-viewer.vue两个文件组成的,其最外层的main.vue是ima

  • 解决elementui中NavMenu导航菜单高亮问题(解决多种情况)

    目录 前言 我在项目中遇到的情况有三种:(vue-cli+elementui) 1.横向菜单 2.纵向菜单 3.嵌套式菜单 代码实现 1.横向菜单 2.纵向菜单 3.嵌套式菜单 前言 如果使用elementui这个框架来开发系统,那么我们几乎都会使用到NavMenu 组件. 我们可能需要菜单根据我们点击的那一项高亮显示,刷新页面了之后还是会相应的高亮显示. elementUI组件官网: https://element.eleme.io/#/zh-CN/component/menu 我在项目中遇到

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

    目录 正文 组件需求分析 组件中用到的知识点 函数式组件 函数式组件的两种定义方式 解决一像素太粗的问题 组件封装 组件封装的效果图 组件封装的代码 正文 本篇文章记录仿写一个el-divider组件细节,从而有助于大家更好理解饿了么ui对应组件具体工作细节.本文是elementui源码学习仿写系列的又一篇文章,后续空闲了会不断更新并仿写其他组件.源码在github上,大家可以拉下来,npm start运行跑起来,结合注释有助于更好的理解. github仓库地址如下:github.com/shu

  • elementui源码学习仿写el-link示例详解

    目录 正文 组件思考 组件的需求 组件的效果图 组件实现分析 给link组件加上链接样式 给link组件加上鼠标悬浮时下划线 通过传参控制是否加上下划线(即:是否加上这个下划线类名) 使用v-bind="$attrs"兜底a标签的其他的未在props中声明的参数 代码 使用代码 封装组件代码 正文 本篇文章记录仿写一个el-link组件细节,从而有助于大家更好理解饿了么ui对应组件具体工作细节.本文是elementui源码学习仿写系列的又一篇文章,后续空闲了会不断更新并仿写其他组件.源

  • Vue源码学习记录之手写vm.$mount方法

    目录 一.概述 二.使用方式 三.完整版vm.$mount的实现原理 四.只包含运行时版本的vm.$mount的实现原理 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.概述 在我们开发中,经常要用到Vue.extend创建出Vue的子类来构造函数,通过new 得到子类的实例,然后通过$mount挂载到节点,如代码: <div id="mount-point"></div> <!-- 创建构造器 --> var Profile =

  • Bootstrap源码学习笔记之bootstrap进度条

    基本样式 要实现进度条效果要使用两个容器,外容器使用"progress"样式,子容器使用"progress-bar"样式.例如: <div class="progress"> <div class="progress-bar" style="width:40%"></div> </div> progress样式主要设置进度条容器的背景色,容器高度.间距等,pr

  • Android源码学习之组合模式定义及应用

    组合模式定义: Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. 将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性. 如上图所示(截取自<Head First De

  • 通过JDK源码学习InputStream详解

    概况 本文主要给大家介绍了通过JDK源码学习InputStream的相关内容,JDK 给我们提供了很多实用的输入流 xxxInputStream,而 InputStream 是所有字节输入流的抽象.包括 ByteArrayInputStream .FilterInputStream .BufferedInputStream .DataInputStream 和 PushbackInputStream 等等.下面话不多说了,来一起看看详细的介绍吧. 如何阅读JDK源码. 以看核心虚拟机(hotsp

  • vue 2.5.1 源码学习 之Vue.extend 和 data的合并策略

    1. 子类父类 2.Vue.extend()      //创建vue的子类 组件的语法器 Vue.extend(options) Profile().$mount('#app') // 挂在app上,并替换app 新建 initExend ==> Vue.extend 3. strat.data ==> if(!vm){子组件中data的值是一个方法function ==> mergeDataorFn()} // 数据的合并 ==> else {} //通过实例绑定的data 实

  • Vue源码学习之响应式是如何实现的

    目录 前言 一.一个响应式系统的关键要素 1.如何监听数据变化 2.如何进行依赖收集--实现 Dep 类 3.数据变化时如何更新--实现 Watcher 类 二.虚拟 DOM 和 diff 1.虚拟 DOM 是什么? 2.diff 算法--新旧节点对比 三.nextTick 四.总结 前言 作为前端开发,我们的日常工作就是将数据渲染到页面➕处理用户交互.在 Vue 中,数据变化时页面会重新渲染,比如我们在页面上显示一个数字,旁边有一个点击按钮,每次点击一下按钮,页面上所显示的数字会加一,这要怎么

  • Python内建类型str源码学习

    目录 引言 1 Unicode 2 Python中的Unicode 2.1 Unicode对象的好处 2.2 Python对Unicode的优化 3 Unicode对象的底层结构体 3.1 PyASCIIObject 3.2 PyCompactUnicodeObject 3.3 PyUnicodeObject 3.4 示例 4 interned机制 5 总结 引言 “深入认识Python内建类型”这部分的内容会从源码角度为大家介绍Python中各种常用的内建类型. 在介绍常用类型str之前,在上

  • Python内建类型list源码学习

    目录 问题: 1 常用方法 小结: 题外话: 2 list的内部结构:PyListObject 3 尾部操作和头部操作 3.1 尾部操作 3.2 头部操作 4 浅拷贝和深拷贝 4.1 浅拷贝 4.2 深拷贝 4.3 直接赋值 4.4 小结 个人总结: TODO: 5 动态数组 5.1 容量调整 5.2 append() 5.3 insert() 5.4 pop() 5.5 remove() 6 一些问题 问题: “深入认识Python内建类型”这部分的内容会从源码角度为大家介绍Python中各种

随机推荐