一天一个 Element 组件 - Tag
source link: https://shiningdan.github.io/2020/01/30/%E4%B8%80%E5%A4%A9%E4%B8%80%E4%B8%AA-Element-%E7%BB%84%E4%BB%B6-Tag/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
本文是 Element 的组件源码学习系列。
项目源码:ElemeFE/element | GitHub,Tag:v2.13.0
Tag 组件使用文档:Tag 标签
.vue 文件:/packages/tag
.scss 文件:/packages/theme-chalk/tag.scss
.d.ts 文件:/types/tag.d.ts
el-tag
是基于 span
封装的标签组件。因为 Tag 的使用形式,大多为一排多个 Tag 进行选择,所以并没有基于 div
进行封装
Props
首先我们来看一下 el-tag
的 Props,了解使用这个组建的入参:
props: { |
closable
设置 closable
属性可以定义一个标签是否可移除。在显示效果上来说,设置了 closable
的 el-tag
,标签内部靠后,有一个小 x
,点击即可触发 close
事件。
我们开看一下相关的实现方案:
render(h) { |
由于 el-tag
标签的内部,会接收文字或者一些 HTML 子元素,所以 span
标签的第一个子元素,就是先补充 this.$slots.default
。
当设置了 this.cloable
的时候,会在 span
内部追加一个 i
标签,用来显示小小的删除按钮,同时点击删除按钮的时候,会调用 this.handleClose
方法:
handleClose(event) { |
这里有一个细节大家需要注意一下,我们点击 i
标签的时候,触发的事件是 click
事件,但是 el-tag
对外提供的是 close
事件,所以我们要把 click
事件转换成 close
事件。并且为了防止子元素的 click
事件冒泡出去,还需要调用 event.stopPropagation();
。
同样,el-tag
也提供了 click
事件,直接使用的是 span
标签的 click
事件。逻辑非常简单,感觉这样的设计挺冗余的:
handleClick(event) { |
由上,我们可以总结出一些写高级组件的事件处理的一些套路:
- 高级组件的事件,都是需要主动
emit
出来的,所以我们对于每一个要提供的事件,都需要有对应的handler
函数,虽然这个函数的逻辑可能非常简单 - 所有对外提供的事件,因为事件的冒泡特性,都要考虑一下是不是会互相影响。
type & hit
将这两个属性放在一起介绍,主要是因为这两个属性,都是直接操作 CSS class 来影响样式的,没有太多的逻辑耦合。
const classes = [ |
相关的 CSS 代码为:
@mixin genTheme($backgroundColorWeight, $borderColorWeight, $fontColorWeight, $hoverColorWeight) { |
通过 CSS 相关的代码,我们可以知道:
- 设置了
type
之后,改变了对应的background-color
,border-color
和color
hit
属性决定是否有边框描边,当然改变的是border-color
- 当设置为 Tag 可以删除时,会在
span
中新增一个i
标签来显示删除按钮,对应的 CSS 类名都为el-tag__close
,相关的样式也可以在这里找到。
size & effect
computed: { |
size
和 type
的变化,同样也反应到 span
标签的 CSS 类上,来触发大小的改变,以及主题的变换。
我们来看一下相关的 SCSS 实现:
@include b(tag) { |
在这段 SCSS 里面,基础的 CSS 语法,比如设置 border
,设置 height
之类的,我们都能够看懂。问题是,这段 SCSS 是如何确认当前的主题是 light
还是 dark
,当前的大小是 medium
还是 small
呢?
答案都在 m
这个函数上。
Element 在对 CSS 类进行命名的时候,使用的是 BEM 命名法。具体什么是 BEM 命名法,大家可以去自行搜一下,我们这里主要看 BEM 命名法如何在 el-tag
中应用的:
当设置主题 effect
为 dark
,设置大小 size
为 small
的时候
const classes = [ |
el-tag
对应的 span
标签会被加上两个 CSS 类名:el-tag--small
和 el-tag--dark
。在 BEM 命名法中,B 代表的 block 为 tag
,M 代表的 module 为 small
和 dark
。
这里的 b
函数和 m
函数,就代表着匹配 block,以及匹配 module 的能力。当 span
标签的 block 为 tag
, module 为 small
和 dark
的时候,就会运行对应的 CSS 代码。
module 为 dark
的 HTML 元素,会被应用定义好的 genTheme
函数,传递对应的颜色设置: genTheme(100%, 100%, 0, 80%);
module 为 small
的 HTML 元素,会被设置 CSS 样式 height: 24px; padding: 0 8px;
等。
@include b(tag) { |
b
函数的定义和 m
函数的实现方法,都可以在 tag.scss
文件的最上面:@import "mixins/mixins";
这个引用中找到。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK