序言
在上一篇文章中,我们已成功搭建起 Vue 按钮组件的基本架构 🏗️,赋予其强大的核心功能与流畅的交互逻辑。此刻,一个功能完备的按钮雏形已然呈现。然而,在追求卓越用户体验的道路上,仅有功能远远不够,样式的精心雕琢同样关键。就如同打造一辆超级跑车,强大的引擎是基础,但炫酷的外观才是吸引众人目光的焦点。接下来,我们将一同踏入按钮组件样式的奇幻世界,探索如何通过色彩 🌈、形状 🔳、阴影 🖤 等元素,赋予按钮独特魅力,使其在前端界面中脱颖而出。
样式 UI 图:设计蓝图引领方向 🗺️
在正式动工之前,还是先给大家展示一下 Element 样式 UI 图。从不同场景下按钮的颜色搭配,到按钮的整体形状,每一个细节都一目了然。
按钮基础样式实现:构建坚实的基石 🧱
在组件库的开发中,为了保证一致性,有些样式往往是统一规范的,例如高度、内外边距以及字体大小等。我们先实现按钮组件那些基本不变的样式,代码如下:
scss
@include b(button) {
display: inline-flex;
vertical-align: middle;
justify-content: center;
align-items: center;
line-height: 1;
white-space: nowrap;
cursor: pointer;
outline: none;
user-select: none;
transition: 0.1s;
padding: 0 getVariableValue('space');
height: getVariableValue('size');
font-size: getVariableValue('font-size');
border-width: getVariableValue('border-width');
border-style: getVariableValue('border-style');
border-radius: getVariableValue('border-radius');
& + & {
margin-left: getVariableValue('space');
}
}
这里利用了全局定义的变量,通过 getVariableValue
函数来获取对应的属性值,就如同从一个装满各种样式配件的宝库中,精准地取出我们需要的零件,为按钮打造出统一、规范的基础样式。实现后的样式效果如下图,可以看到,按钮已经初步具备了整齐、有序的外观,为后续的个性化样式设计奠定了坚实的基础。

实现思路:颜色变幻的魔法密码 🔮
我们知道,按钮在不同场景下的样式区别主要体现在边框颜色、字体颜色以及背景颜色上,并且在默认、禁用、悬停这三种情况下,会展示出不同深度的颜色。那如何实现这种神奇的颜色变化呢?答案就是通过定义变量,巧妙地修改变量的颜色来实现各种情况下的样式变化。接下来,让我们一步步揭开这个魔法的奥秘。
初始化变量、默认值:为魔法准备材料 📦
scss
$button: () !default;
$button: map.merge(
(
'font-color': getVariableValue('font-color'),
'border-color': getVariableValue('border-color'),
'background-color': getVariableValue('fill-color'),
'hover-font-color': getVariableValue('font-color', 'hover'),
'hover-border-color': getVariableValue('color', 'primary', 'light-7'),
'hover-background-color': getVariableValue('color', 'primary', 'light-9'),
'disabled-font-color': getVariableValue('font-color', 'disabled'),
'disabled-border-color': getVariableValue('border-color', 'light'),
'disabled-background-color': getVariableValue('fill-color'),
),
$button
);
@include b(button) {
@include set-all-variable-from-map('button', $button);
}
首先,咱们来看看代码开头部分的变量定义与合并操作。
$button: ()!default;
这行代码声明了一个名为 $button
的 SCSS 变量,初始它被设置为空映射(map),这里的 !default
标记意味着如果这个变量在别处已经被定义过了,那它就会保留之前的值,否则就使用当前这个空映射的初始设定,这样的写法增加了代码的灵活性和可扩展性。
紧接着,$button: map.merge(...)
这部分可是关键所在。map.merge
是将两个映射合并成一个新的映射,并且后面传入的映射参数会覆盖前面相同键名的值。
然后各个属性通过getVariableValue
函数获取默认值。最后通过 set-all-variable-from-map('button', $button)
将这些映射的属性设置成变量,如'font-color': getVariableValue('font-color'),
属性将会编译成--n-button-font-color: var(--n-font-color)
,var(--n-font-color)
就是getVariableValue('font-color')
拿到的具体的变量值。
设置初始样式:点亮魔法的第一束光 🌟
scss
@include b(button) {
color: getVariableValue('button', 'font-color');
border-color: getVariableValue('button', 'border-color');
background-color: getVariableValue('button', 'background-color');
&:hover {
color: getVariableValue('button', 'hover-font-color');
border-color: getVariableValue('button', 'hover-border-color');
background-color: getVariableValue('button', 'hover-background-color');
}}
拿color: getVariableValue('button', 'font-color')
这个属性举例,最后会编译成color: var(--n-button-font-color)
。这段代码让按钮在默认状态下呈现出我们设定的颜色,并且在鼠标悬停时,能够巧妙地变换颜色,给用户带来直观的交互反馈。到此我们的基本工作已经做完。实现的效果如下图:
scene
场景样式具体实现:场景变换的魔法盛宴 🎉
接下来,我们要为按钮在不同场景下赋予独特的色彩风格,让它能够根据不同的使用场景,展现出最合适的外观。
辅助混入:魔法配方的秘籍 📜
scss
@mixin button-action-scene-color($scene) {
$scene-color-types: (
'': (
'font-color': (
'color',
'white'
),
'border-color': (
'color',
$scene
),
'background-color': (
'color',
$scene,
),
),
'hover': (
'font-color': (
'color',
'white'
),
'border-color': (
'color',
$scene,
'light-3',
),
'background-color': (
'color',
$scene,
'light-3',
),
),
'disabled': (
'font-color': (
'color',
'white'
),
'border-color': (
'color',
$scene,
'light-5',
),
'background-color': (
'color',
$scene,
'light-5',
),
)
);
@each $action, $colorMap in $scene-color-types {
@each $color, $list in $colorMap {
@include set-variable-from-global((button, $action, $color), $list);
}
}
}
这个名为 button-action-scene-color
的混入接收 $scene
参数,用来指定具体场景。
在混入内部,定义了 $scene-color-types
这个映射,它划分了默认、悬停、禁用三种状态,且针对每种状态设置了字体、边框、背景颜色的相关取值规则。比如默认状态下,边框和背景颜色会依据 $scene
参数来确定,悬停和禁用状态则在此基础上结合如 light-3
、light-5
等深浅标识获取相应颜色值。
而后通过两层嵌套的 @each
循环,调用 set-variable-from-global
,将各状态下设定好的颜色值应用到按钮对应的属性上,从而实现不同场景及状态下按钮颜色的准确呈现,助力打造出美观又符合交互逻辑的按钮样式。
场景循环:魔法的华丽绽放 🔥
在按钮组件样式设定中,下面这段 "场景循环" 代码有着关键作用。
scss
@each $scene in $sceneTypes {
@include m($scene) {
@include button-action-scene-color($scene);
}
}
这里的 @each
循环会遍历 $sceneTypes
里的元素。在每次循环时,先是通过 @include m($scene)
,接着 @include button-action-scene-color($scene)
会依据该场景进一步设置如默认、悬停、禁用等不同状态下的颜色样式,以此让按钮在各个场景下都能展现出合适的外观,整体实现了场景样式的有序且合理的应用。
编译后的代码大致如下:
scss
.n-button--primary {
--n-button-font-color: var(--n-color-white);
--n-button-border-color: var(--n-color-primary);
--n-button-background-color: var(--n-color-primary);
--n-button-hover-font-color: var(--n-color-white);
--n-button-hover-border-color: var(--n-color-primary-light-3);
--n-button-hover-background-color: var(--n-color-primary-light-3);
--n-button-disabled-font-color: var(--n-color-white);
--n-button-disabled-border-color: var(--n-color-primary-light-5);
--n-button-disabled-background-color: var(--n-color-primary-light-5);
}
不同场景下的样式如下图: 可以看到,按钮在不同场景下,如
primary
、success
等,都展现出了独特的颜色风格,无论是正常状态、悬停还是禁用,都能给用户带来清晰的视觉区分和良好的交互体验。
完整组件样式:魔法成品的惊艳呈现 🌟
其它的样式实现与上文实现类似,具体的不一一赘述了,可以到下方提到的仓库中查看具体代码。最后完整实现如下图:
此时的按钮组件,已经成为了一个功能与颜值并存的完美作品,它在不同场景下都能展现出独特的魅力,为用户带来流畅、美观的交互体验。
最后在packages/components/button
目录下新增index.ts
作为组件的入口文件,负责整合组件。
🦀🦀感谢看官看到这里,如果觉得文章不错的话🙌,点个关注不迷路⭐。
诚邀您加入我的微信技术交流群🎉,群里都是志同道合的开发者👨💻,大家能一起交流分享摸鱼🐟。期待与您在群里相见🚀,咱们携手在开发路上共同进步✨ !
👉点我
感谢各位大侠一路相伴,实在感激! 不瞒您说,在下还有几个开源项目 📦,它们就像精心培育的幼苗 🌱,急需您的浇灌。要是您瞧着还不错,麻烦动动手指,给它们点亮几颗 Star ⭐,您的支持就是它们成长的最大动力,在此谢过各位大侠啦!
Nova UI
组件库:github.com/gmingchen/n...- 基于 Vue3 + Element-plus 管理后台基础功能框架
- 预览:admin.gumingchen.icu
- Github:github.com/gmingchen/a...
- Gitee:gitee.com/shychen/agi...
- 基础版后端:github.com/gmingchen/j...
- 文档:admin.gumingchen.icu/doc/
- 基于 Vue3 + Element-plus + websocket 即时聊天系统
- 基于 node 开发的后端服务:github.com/gmingchen/n...