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

目录
  • 正文
  • 组件思考
    • 组件的需求
  • 组件的效果图
  • 组件实现分析
    • 给link组件加上链接样式
    • 给link组件加上鼠标悬浮时下划线
    • 通过传参控制是否加上下划线(即:是否加上这个下划线类名)
    • 使用v-bind="$attrs"兜底a标签的其他的未在props中声明的参数
  • 代码
    • 使用代码
    • 封装组件代码

正文

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

github仓库地址如下:https://github.com/shuirongsh...

组件思考

简而言之,el-link组件就是给a标签包了一层,加上一些样式。故link组件除了拥有a标签的功能,还需要有一些能够使用的样式效果。所以,我们仿写这个组件标签的时候主要是复习一下传参的变量和样式的搭配,从而实现我们需要的效果

组件的需求

  • link组件加上不同类型的链接样式,比如普通样式、成功样式、警告样式、危险样式的链接样式
  • link组件加上鼠标悬浮时下划线。封装组件中使用的是伪元素搭配border-bottom实现的
  • 通过传参去控制link组件什么时候有下划线,什么时候没有下划线
  • 另外,也需要考虑组件会被禁用,禁用时,不能点击,不能跳转,且更换一下样式效果
  • 同时,link组件跳转链接时的一些操作
  • 也要是考虑到link组件需要搭配小图标去使用(本例中以饿了么icon为例)

组件的效果图

组件实现分析

给link组件加上链接样式

这里使用动态class的数组用法去控制,如下简单例子:

// html
<a
  :class="[
    'myLink',
    type
]"
>
// js
props:{
    type: String, // 标签颜色的类型
}
// css
.primary { color: #2d8cf0; }
.success { color: #19be6b; }
.warning { color: #f90; }
.danger { color: #ed4014; }

由上,比如传递的type参数值为success,那么a标签就会加上一个success的类名,这样的话,就会找到对应css中的类名,从而呈现相应的颜色效果(当然type的值在底下css中要有对应的)

给link组件加上鼠标悬浮时下划线

其实类似这种,悬浮下划线,悬浮上划线,悬浮特殊背景控制。大致可以归纳为在主要dom旁边加上一个小东西,都可以考虑使用伪元素

关于啥是伪元素,这里不赘述

我们看下方的鼠标悬浮上划线和下划线的效果图,这个效果图就是使用伪元素搭配定位以及border去实现的

代码:

// css
span {
     font-size: 24px;
     position: relative;
}
span:hover::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 0;
    /* 定位控制 */
    top: 2px;
    border-top: 1px solid red;
}
span:hover::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 0;
    /* 定位控制 */
    bottom: -2px;
    border-bottom: 1px solid red;
}
// html
<span>早上好,程序猿兽们</span>

通过传参控制是否加上下划线(即:是否加上这个下划线类名)

这里依然是使用动态class的数组用法,在数组中书写四元表达式,简约代码如下:

<a
    :class="[
      'myLink',
       hideUnderline ? '' : disabled ? '' : 'underline'
    ]"
  >

大意:即不去隐藏下划线,又不去禁用这个link组件的时候,才加上underline类名,才产生下划线

使用v-bind="$attrs"兜底a标签的其他的未在props中声明的参数

<a
    :href="disabled ? null : href" rel="external nofollow"  rel="external nofollow"
    v-bind="$attrs"
  >

我们知道a标签中有很多原生属性,如下图:

这么多a标签的属性,我们不可能在封装的组件的时候,如果把每一个属性都在props中声明,倒是有些麻烦。所以此时$attr就应运而生了。关于$attr$listener的用法,这里也不赘述,大家只要记得$attr是做参数属性兜底的即可。

详情可看笔者之前写的文章:https://www.jb51.net/article/249437.htm

组件需求由于篇幅原因就不赘述了,详情见代码中注释(毕竟这个组件其实也挺简单的),接下来上代码

代码

演示的话,直接复制粘贴即可,结合注释更好理解。注意my-divider组件是之前封装的组件。

笔者封装的组件和官方封装的组件在一些细节的地方可能略有不同,算是多一个解法思路吧 ^o^

使用代码

<template>
  <div class="box">
    <my-divider lineType="dashed" content-position="left"
      >五种链接样式</my-divider
    >
    <my-link>默认超链接</my-link>
    <my-link type="primary">primary超链接</my-link>
    <my-link type="success">success超链接</my-link>
    <my-link type="warning">warning超链接</my-link>
    <my-link type="danger">danger超链接</my-link>
    <my-divider lineType="dashed" content-position="left"
      >是否有下划线</my-divider
    >
    <my-link>默认有下划线</my-link>
    <my-link hideUnderline>也可隐藏下划线</my-link>
    <my-divider lineType="dashed" content-position="left"
      >禁用链接样式</my-divider
    >
    <my-link disabled>禁用|默认超链接</my-link>
    <my-link type="primary" disabled>禁用|primary超链接</my-link>
    <my-link type="success" disabled>禁用|success超链接</my-link>
    <my-link type="warning" disabled>禁用|warning超链接</my-link>
    <my-link type="danger" disabled>禁用|danger超链接</my-link>
    <my-divider lineType="dashed" content-position="left"
      >添加href和target原生属性</my-divider
    >
    <my-link type="primary" href="https://www.baidu.com/" rel="external nofollow" >默认self跳转</my-link>
    <my-link type="success" target="_blank" href="https://cn.bing.com/" rel="external nofollow"
      >支持原生属性target等</my-link
    >
    <my-divider lineType="dashed" content-position="left"
      >通过icon属性或者直接在默认插槽中添加图标</my-divider
    >
    <my-link type="primary" icon="el-icon-share">默认图标在前方</my-link>
    <my-link type="success" icon="el-icon-share" back
      >back属性控制图标在后方</my-link
    >
    <my-link type="primary"
      ><i class="el-icon-goods"></i>默认插槽前方加图标</my-link
    >
    <my-link type="success"
      >默认插槽后方加图标 <i class="el-icon-goods"></i
    ></my-link>
    <my-divider lineType="dashed" content-position="left"
      >绑定事件使用</my-divider
    >
    <my-link @click="clickThis" type="danger" icon="el-icon-aim"
      >点击这个哦</my-link
    >
  </div>
</template>
<script>
export default {
  methods: {
    clickThis() {
      console.log("注意:当myLink禁用或有href属性时,点击事件失效");
    },
  },
};
</script>

封装组件代码

<template>
  <!--
       hideUnderline ? '' : disabled ? '' : 'underline',
       先看hideUnderline是否为true,为true则要隐藏下划线,即不加underline类名
       再看disabled是否为true,为true则禁用,禁用也要隐藏下划线,即也不加underline类名
       若既不隐藏下划线又不禁用链接,则加上underline类名用于显示下划线
   -->
  <a
    :href="disabled ? null : href" rel="external nofollow"  rel="external nofollow"
    :class="[
      'myLink',
      hideUnderline ? '' : disabled ? '' : 'underline',
      type,
      disabled ? 'toDisabled' : '',
    ]"
    v-bind="$attrs"
    @click="handleClick"
  >
    <!--
       这里加上v-bind="$attrs"是为了传递更多的属性,做一个参数兜底的功能效果。因为a标签还有其他很多属性,如:
       target、download、type等。props中未声明的参数,会被$attr兜底交给a标签使用。故加了v-bind="$attrs"以后,
       在外层my-link标签上,我们便可正常使用除props中声明的属性了,如使用target原生属性:<my-link target="_blank" href="xxx" rel="external nofollow" />
    -->
    <!-- 内容区 -->
    <span class="aContent" :class="{ spaceC: icon, back: back }">
      <i :class="icon" v-if="icon"></i>
      <span><slot></slot></span>
    </span>
  </a>
</template>
<script>
export default {
  name: "myLink",
  props: {
    href: String, // a标签的href属性,用于跳转
    disabled: Boolean, // 是否禁用超链接
    type: String, // 标签颜色的类型
    // 是否隐藏下划线
    hideUnderline: {
      type: Boolean,
      default: false, // 默认不隐藏下划线,默认展示下划线
    },
    icon: String, // 使用饿了么UI的小图标
    back: Boolean, // 设置图标在内容后方
  },
  methods: {
    handleClick(event) {
      // 禁用状态下不允许传递事件
      if (this.disabled) {
        return;
      }
      // 有链接了也不允许传递事件
      if (this.href) {
        return;
      }
      // 没有禁用没有链接,便可正常传递事件
      this.$emit("click", event);
    },
  },
};
</script>
<style lang="less" scoped>
// 默认样式
.myLink {
  display: inline-block;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  color: #666; // 默认颜色,当然也可以使用type类型的配色
  text-decoration: none; // 去除a标签默认的下划线(不使用自带的下划线效果)
  position: relative; // 定位搭配伪元素实现悬浮下划线效果
  margin: 4px;
  .aContent {
    display: flex;
    align-items: center;
  }
  // 当传的有图标的时候,把第一个元素加上一个右边距,产生间距
  .spaceC > :first-child {
    margin-right: 4px;
  }
  // 控制弹性盒方向,控制图标在后方位置(默认前方位置)
  .back {
    flex-direction: row-reverse;
  }
  // 注意这里要覆盖上方spaceC的样式
  .back > :first-child {
    margin: 0 0 0 4px;
  }
}
// 通过变量控制是否有这个underline类名,从而控制是否有下划线
.underline:hover::after {
  // 这样的话,元素在哪,下划线就在哪里
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  bottom: -2px;
  // 注意,这里不设置颜色,就会跟随参考定位的元素的颜色了
  border-bottom: 1px solid;
}
// 下方的配色是抄iview的
.primary {
  color: #2d8cf0;
}
.success {
  color: #19be6b;
}
.warning {
  color: #f90;
}
.danger {
  color: #ed4014;
}
// 通过透明度模拟禁用的颜色样式效果,要不然要写两份颜色会稍微麻烦一些
.toDisabled {
  opacity: 0.36;
  cursor: not-allowed;
}
</style>

以上就是elementui源码学习仿写el-link示例详解的详细内容,更多关于elementui仿写el-link示例的资料请关注我们其它相关文章!

(0)

相关推荐

  • element-ui中el-form-item内的el-select该如何自适应宽度

    目录 问题: 详细描述: 总结 问题: 想让el-select自适应宽度,即 label宽度 + el-select宽度可以填满一行,想要实现这样的效果 详细描述: 项目中的代码如下,给 el-select 设置了 style=“width:100%” 没有作用,不论布局是变大变小,el-select 的宽度都不会有变化,就像下图所示 我只有在el-select中设置固定的值如 style="width:100px"才有作用.下面是我的代码,不知道是不是我对width的设置方法有错 &

  • 去除element-ui中Dialog对话框遮罩层方法详解

    目录 前言 modal 属性 示例代码: 前言 本文主要介绍了如何去除 element-ui 中 Dialog 对话框遮罩层的方法,并给出了示例代码以及页面效果作为参考. modal 属性 在使用element-ui的Dialog时,默认会有遮罩层,想要去除遮罩层,官方文档给出了 modal 属性: modal 是一个布尔值,表示是否需要遮罩层: 然而,将 modal 赋值为 false 时并不生效: 这里官方文档也给出了提示: 当 modal 的值为 false 时,请一定要确保 append

  • Vue中使用element-ui给按钮绑定一个单击事件实现点击按钮就弹出dialog对话框

    目录 1.需求描述 2.功能实现 1.创建按钮 2.创建对话框 3.对话框与按钮的绑定 3.对话框表单的改造 4.对“状态”Switch开关所提交的类型进行修改 5.完整代码 总结 1.需求描述 想要实现点击一个按钮就弹出一个对话框,在对话框中可输入数据进行提交,在点击取消时对话框关闭 2.功能实现 1.创建按钮 在element中把找到按钮的代码放到div里 <el-row> <el-button type="primary" plain>新增</el-

  • element-ui dialog弹窗增加全屏功能(推荐)

    目录 一.定义全局变量 dialogFull 用来控制弹窗 二.dialog标签添加全局属性绑定 三.设置title区域的自定义 四.css样式部分: 完成效果图: 一.定义全局变量 dialogFull 用来控制弹窗 dialogFull:false, 二.dialog标签添加全局属性绑定 :fullscreen="dialogFull" 三.设置title区域的自定义 <template slot="title"> <div class=&qu

  • vue+element-ui前端使用print-js实现打印功能(可自定义样式)

    目录 下载依赖 使用print-js 实现打印功能 需要打印的内容 按钮调用打印函数 打印函数 调整打印字体大小 参数 总结 print-js官网链接: https://printjs.crabbly.com/ 下载依赖 npm install print-js --save 在package.json文件中增加print-js依赖. "dependencies": { "axios": "^0.19.2", "babel-polyfi

  • 使用element-ui的upload组件上传代码包时遇到的问题小结

    1.在工作中使用element-ui的upload组件时,遇到一个问题就是这个upload会自动发送一个http请求,即使你使用了http-request自定义上传覆盖默认上传函数,也会导致在控制台里多出一个请求,并且当项目中使用proxy代理挂载到原型上类似的请求接口方法的时候,必须知道原请求路径放在他的actions属性中,才可以使它的多余请求不报错,可能说的有一些混乱,接下来用代码演示: export function proxy (interfaceId, proxyOptions =

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

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

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

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

  • Volley源码之使用方式和使用场景详解

    概述 Volley是Google在2013年推出的一个网络库,用于解决复杂网络环境下网络请求问题.刚推出的时候是非常火的,现在该项目的变动已经很少了.项目库地址为https://android.googlesource.com/platform/frameworks/volley 通过提交历史可以看到,最后一次修改距离今天已经有一段时间了.而volley包的release版本也已经很久没有更新了. author JeffDavidson<jpd@google.com> SunMar1316:3

  • Git基础学习之分支操作的示例详解

    目录 1.新建一个分支并且使分支指向指定的提交对象 2.思考 3.项目分叉历史的形成 4.分支的总结 1.新建一个分支并且使分支指向指定的提交对象 使用命令:git branch branchname commitHash. 我们现在本地库中只有一个 master 分支,并且在 master 分支有三个提交历史. 需求:创建一个 testing 分支,并且testing 分支指向 master 分支第二个版本. # 1.查看提交历史记录 L@DESKTOP-T2AI2SU MINGW64 /j/

  • TensorFlow人工智能学习数据合并分割统计示例详解

    目录 一.数据合并与分割 1.tf.concat() 2.tf.split() 3.tf.stack() 二.数据统计 1.tf.norm() 2.reduce_min/max/mean() 3.tf.argmax/argmin() 4.tf.equal() 5.tf.unique() 一.数据合并与分割 1.tf.concat() 填入两个tensor, 指定某维度,在指定的维度合并.除了合并的维度之外,其他的维度必须相等. 2.tf.split() 填入tensor,指定维度,指定分割的数量

  • 人工智能学习Pytorch教程Tensor基本操作示例详解

    目录 一.tensor的创建 1.使用tensor 2.使用Tensor 3.随机初始化 4.其他数据生成 ①torch.full ②torch.arange ③linspace和logspace ④ones, zeros, eye ⑤torch.randperm 二.tensor的索引与切片 1.索引与切片使用方法 ①index_select ②... ③mask 三.tensor维度的变换 1.维度变换 ①torch.view ②squeeze/unsqueeze ③expand,repea

  • 人工智能学习Pytorch梯度下降优化示例详解

    目录 一.激活函数 1.Sigmoid函数 2.Tanh函数 3.ReLU函数 二.损失函数及求导 1.autograd.grad 2.loss.backward() 3.softmax及其求导 三.链式法则 1.单层感知机梯度 2. 多输出感知机梯度 3. 中间有隐藏层的求导 4.多层感知机的反向传播 四.优化举例 一.激活函数 1.Sigmoid函数 函数图像以及表达式如下: 通过该函数,可以将输入的负无穷到正无穷的输入压缩到0-1之间.在x=0的时候,输出0.5 通过PyTorch实现方式

  • python神经网络学习数据增强及预处理示例详解

    目录 学习前言 处理长宽不同的图片 数据增强 1.在数据集内进行数据增强 2.在读取图片的时候数据增强 3.目标检测中的数据增强 学习前言 进行训练的话,如果直接用原图进行训练,也是可以的(就如我们最喜欢Mnist手写体),但是大部分图片长和宽不一样,直接resize的话容易出问题. 除去resize的问题外,有些时候数据不足该怎么办呢,当然要用到数据增强啦. 这篇文章就是记录我最近收集的一些数据预处理的方式 处理长宽不同的图片 对于很多分类.目标检测算法,输入的图片长宽是一样的,如224,22

  • Go语言学习教程之反射的示例详解

    目录 介绍 反射的规律 1. 从接口值到反射对象的反射 2. 从反射对象到接口值的反射 3. 要修改反射对象,该值一定是可设置的 介绍 reflect包实现运行时反射,允许一个程序操作任何类型的对象.典型的使用是:取静态类型interface{}的值,通过调用TypeOf获取它的动态类型信息,调用ValueOf会返回一个表示运行时数据的一个值.本文通过记录对reflect包的简单使用,来对反射有一定的了解.本文使用的Go版本: $ go version go version go1.18 dar

  • React学习笔记之列表渲染示例详解

    前言 本文主要给大家介绍了关于React列表渲染的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 示例详解: 列表渲染也很简单,利用map方法返回一个新的渲染列表即可,例如: const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li>{number}</li> ); ReactDOM.render( <ul>{listItems}<

随机推荐