本文是 Element 的组件源码学习系列。
项目源码:ElemeFE/element | GitHub,Tag:v2.13.0
Link 组件使用文档:Link 文字链接
.vue 文件:/packages/link
.scss 文件:[/packages/theme-chalk/link.scss](https://github.com/ElemeFE/element/blob/dev/packages/theme-chalk/src/link.scss
.d.ts 文件:/types/link.d.ts
el-link 的实现方案,基于原生 <a> 元素
Props
首先我们来看一下 el-link 的 Props,了解使用这个组建的入参:
1 | props: { |
type
type 字段是用来控制 el-link 组件的样式(主要是颜色),并不影响行为,我们来看一下实现方案:
首先,用户传入 type 属性,type 只会被自动注入到 a 标签的样式类中:
1 | <a |
如果设置了 type 为 success,则 a 标签会自动添加 el-link--success 的样式类。
我们来看一下 el-link--success 这个样式类做了什么,打开 scss 文件,/packages/theme-chalk/link.scss
定位到这一段相关的代码:
1 | @import "common/var"; |
首先,引入 scss 全局颜色变量,然后定义 el-link 标签使用的 $typeMap 变量,将 type 和 颜色变量映射起来。
其次,遍历映射表 $typeMap,创建 el-link--#{$type} 样式类。比如当 type 为 success 的时候,就映射到 el-link--success 样式类了。
我们可以通过样式类的定义,大致看到 element 具体做了哪些样式的修改,比如
- 设置了
el-link标签内的文字颜色color - 设置鼠标 hover 上去后,文字颜色会有 80% 的透明度
- 设置了
disable属性后,50% 的透明度 - 设置了
underline属性后,hover:after伪元素也要设置边框颜色
所以当 <a> 标签设置了 el-link--success 这个样式类的时候,会应用到 scss 中 type 为 success的样式。
disable
同理,disable 属性设置后,对应也是修改的 <a> 标签的样式类,以及 href 属性:
1 | <a |
从样式上面来说,输了参考 type 中,有 disable 相关的样式改变外,disabled 还设置了鼠标上移时的鼠标样式反馈:
1 | @include when(disabled) { |
除此以外,还有一个细节:当设置 disabled 的时候,点击这个链接应该是没有跳转行为的。此时,HTML 中的 <a> 标签,应该没有 href 这个属性。经过测试,如果是设置 href="",点击 <a> 标签会重复跳转当前页面。
1 | # 点击不会跳转 |
underline
underline 属性的设置,也是反映到 <a> 中 class 的变化。
1 | <a |
el-link 有一个比较细节的地方,就是它的下划线,并没有使用 HTML <a> 的原生 text-decoration: underline 属性,估计是满足不了设计师的设计,太丑了 hhhh。
其实现方案是,创建一个伪元素::after,通过 position: absolute 设置伪元素和当前 <a> 标签的位置与大小重合。设置 content: "" 设置伪元素没有内容,不会影响 <a> 标签内的内容。最后设置 border-bottom,来自定义下划线的样式。即 el-link 的下划线,其实是伪元素的 border-bottom 来模拟的。
参考 SCSS 的实现部分:
1 | @include when(underline) { |
slot 与 icon
这两部分放在一起,是因为 slot 与 icon 属性,都是在 <a> 标签的子元素:
1 | <a> |
从这段代码中可以看出来,el-link 支持 icon 属性,也支持默认 slot,以及具名 slot=icon,虽然具名 slot 并没有在例子中体现出来。
Template
v-bind="$attrs"
在封装 <a> 的时候,有一个属性大家要注意:
1 | <a v-bind="$attrs"></a> |
通过 v-bind="$attrs" 这种方法,可以将 el-link 中非 props 属性都传给 <a> 标签,这样我们在封装高级组件的时候,特别是封装基础标签的高级组件,不同将该标签的每一个属性都通过 props 单独设置一遍,这在封装基础 HTML 标签的时候很重要。(PS: 为什么 el-button 没有设置 v-bind="$attrs" 呢?我暂时没想出来,大家知道的,非常欢迎在下面留言,我会补充到文章里的~)
JS
click 事件
1 | <template> |
当设置了 disabled 属性,或者没有设置 href 属性的时候,我们可以通过设置 el-link 的 click 事件,来监听 a 标签的点击事件。
CSS
CSS 相关的源码解读,之后再补充