本篇文章记录仿写一个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]">// jsprops:{ 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
去实现的
代码:
// cssspan { 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" v-bind="$attrs" >
咱们晓得a
标签中有很多原生属性,如下图:
这么多a
标签的属性,咱们不可能在封装的组件的时候,如果把每一个属性都在props
中申明,倒是有些麻烦。所以此时$attr
就应运而生了。对于$attr
和$listener
的用法,这里也不赘述,大家只有记得$attr
是做参数属性兜底的即可。详情可看笔者之前写的文章:https://segmentfault.com/a/11...
组件需要因为篇幅起因就不赘述了,详情见代码中正文(毕竟这个组件其实也挺简略的),接下来上代码
代码
演示的话,间接复制粘贴即可,联合正文更好了解。留神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/">默认self跳转</my-link> <my-link type="success" target="_blank" href="https://cn.bing.com/" >反对原生属性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" :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"/> --> <!-- 内容区 --> <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>