本文是 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 相关的源码解读,之后再补充