05 - Vue3 UI Framework - Button 组件
官网基本做好了,接下来开始做核心组件
返回阅读列表点击 这里
目录准备
在项目 src
目录下创建 lib
文件夹,用来存放所有的核心组件吧。然后再在 lib
文件夹下创建 Button.vue
文件。
您也可以进行结构化设计,比如,这里就不进行了。
|-lib
|-Button
|- Button.vue
|- Button.ts
|_ Button.scss
需求分析
惯例先行需求分析
- 多种类基础
Button
,包含警告、成功、危险等 - 允许设置
Button
为禁用状态 - 不止有传统
Button
,还可以有文字或链接形式 - 当处于加载中,
Button
应当显示 - 有不同的尺寸可供选择
- 应当允许更换颜色
- 当鼠标放置于
Button
上、鼠标按下未松开、处于加载中等状态时,应当变更背景色 - 允许用户自定义
Button
上显示的文本
那么可以整理出以下参数表格
参数 | 含义 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
level | 默认类型 | string | default / plain / primary / success / info / warning / danger | default |
disabled | 是否禁用 | boolean | false / true | false |
theme | 式样 | string | button / link / text | button |
loding | 是否加载中 | boolean | false / true | false |
size | 尺寸 | string | middle / small / large | middle |
color | 颜色 | string | 任意合法颜色值 | #f3678e |
第 7 条,可以通过设置一个遮罩层来实现,只要遮罩层变色,背景色也等效变色
第 8 条,可以通过插槽实现,注意 vue3
不建议使用具名插槽
骨架
容易得到如下骨架
<template>
<button
class="jeremy-button"
:theme="theme"
:level="level"
:size="size"
:style="{ '--color': color }"
:disabled="disabled"
:loading="loading"
>
<div class="jeremy-button-mask"></div>
<span class="jeremy-button-loadingIndicator" v-if="loading"></span>
<slot></slot>
</button>
</template>
首先,本质应当是一个 button
元素,在此基础上,将参数列表中整理出来的每个参数,都使用 v-bind
绑定到 button
上
注意,此处绑定 color
,必须是如上例一样,绑定到 --color
属性上,才可以在 css
中使用 css3
语法 var()
读取,在 css
小节会再解释,此处略
之后,在 button
内
- 放置一个遮罩层,用于变色
- 放置一个”加载中”的动画,用于在加载中状态下显示
- 放置一个默认插槽,用于传递用户自定义的文本
然后为上述元素配置各自的 class
名称,骨架就完成了。
功能
显然,参数列表中整理出来的内容,一定来自引用该组件的地方的传入,先根据参数列表,写好 ts
声明:
declare const props: {
theme?: "button" | "link" | "text";
level?:
| "default"
| "plain"
| "primary"
| "success"
| "info"
| "warning"
| "danger";
size?: "middle" | "small" | "large";
color: string;
disabled: boolean;
loading: boolean;
};
然后在 export default
中,写入我们的参数
export default {
install: function (Vue) {
Vue.component(this.name, this);
},
name: "JeremyButton",
props: {
theme: {
type: String,
default: "button",
},
level: {
type: String,
default: "default",
},
size: {
type: String,
default: "middle",
},
color: {
type: String,
default: "#8c6fef",
},
disabled: {
type: Boolean,
default: false,
},
loading: {
type: Boolean,
default: false,
},
},
};
对于事件绑定,因为我们设计的组件只有一个唯一的根元素,所以对于外部传递过来的事件,会自动绑定到组件的根元素上面。
样式表
注意 :UI
库的样式表一般不要加 scoped
修饰符,为了尽可能减少对用户样式表的影响,方便用户 DIY
特别注意 : button
元素会有默认黑色外边框,不属于 border
,必须通过 outline: none;
才能消除
然后,我们使用 css3
的 var()
语法,取得我们通过 ts
绑定到 style
上的 --color
属性
为什么是 --color
而不是 color
?因为 var()
语法要求这个参数必须是 --
开头,才可以正常访问到
对于遮罩层,采用淡出到白色即可实现,原理此处不解释了
最后,对于多种不同的 button
,可以使用 scss
提供的 mixin / include
语法来实现,完整代码如下:
$theme-color: var(--color);
$base-mask: fade-out(#fff, 0.7);
$active-mask: fade-out(#fff, 0.5);
$h: 32px;
$radius: 4px;
@keyframes jeremy-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.jeremy-button {
position: relative;
display: inline-block;
padding: 10px 16px;
color: white;
border-radius: $radius;
border: none;
font-size: 16px;
cursor: pointer;
white-space: nowrap;
transition: background-color 250ms;
outline: none;
:focus {
outline: none;
}
> .jeremy-button-mask {
position: absolute;
display: inline-block;
height: 100%;
width: 100%;
left: 0;
top: 0;
border-radius: $radius;
&:hover {
background: $base-mask;
}
}
&[loading="true"],
&[disabled] {
cursor: not-allowed;
> .jeremy-button-mask {
pointer-events: none;
}
}
> .jeremy-button-loadingIndicator {
width: 14px;
height: 14px;
display: inline-block;
margin-right: 4px;
border-radius: 8px;
border-style: solid;
border-width: 2px;
animation: jeremy-spin 1s infinite linear;
}
}
@mixin layout($color) {
$loading-color: fade-out(black, 0.7);
background: $color;
&:active {
> .jeremy-button-mask {
background: $active-mask;
}
}
> .jeremy-button-loadingIndicator {
border-color: $loading-color $loading-color $loading-color transparent;
}
&[loading="true"],
&[disabled] {
> .jeremy-button-mask {
background: $base-mask;
}
}
}
.jeremy-button[theme="button"] {
$color: $theme-color;
@include layout($color);
}
.jeremy-button:not([theme="button"]) {
padding: 0;
background: white;
color: black;
&:hover {
color: $theme-color;
}
}
.jeremy-button[theme="link"] {
text-decoration: underline;
}
.jeremy-button[level="plain"] {
$base-color: $theme-color;
@include layout(white);
color: black;
> .jeremy-button-mask {
border: 1px solid rgb(187, 187, 187);
}
&:not([loading="true"]):not([disabled]) {
&:hover {
> .jeremy-button-mask {
border: 1px solid $base-color;
}
color: $base-color;
}
}
}
.jeremy-button[level="primary"] {
$color: #29adfa;
@include layout($color);
}
.jeremy-button[level="success"] {
$color: rgb(103, 194, 58);
@include layout($color);
}
.jeremy-button[level="info"] {
$color: #808080;
@include layout($color);
}
.jeremy-button[level="warning"] {
$color: rgb(230, 162, 60);
@include layout($color);
}
.jeremy-button[level="danger"] {
$color: rgb(245, 108, 108);
@include layout($color);
}
.jeremy-button[size="large"] {
padding: 14px 24px;
}
.jeremy-button[size="small"] {
padding: 6px 10px;
}
以上,button
组件就完成了! :happy:
测试一下
感谢阅读
05 - Vue3 UI Framework - Button 组件的更多相关文章
- 06 - Vue3 UI Framework - Dialog 组件
做完按钮之后,我们应该了解了遮罩层的概念,接下来我们来做 Dialog 组件! 返回阅读列表点击 这里 需求分析 默认是不可见的,在用户触发某个动作后变为可见 自带白板卡片,分为上中下三个区域,分别放 ...
- 10 - Vue3 UI Framework - Tabs 组件
标签页是非常常用的组件,接下来我们来制作一个简单的 Tabs 组件 返回阅读列表点击 这里 需求分析 我们先做一个简单的需求分析 可以选择标签页排列的方向 选中的标签页应当有下划线高亮显示 切换选中时 ...
- 08 - Vue3 UI Framework - Input 组件
接下来再做一个常用的组件 - input 组件 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 input 组件有两种类型,即 input 和 textarea 类型 当类型为 ...
- 09 - Vue3 UI Framework - Table 组件
接下来做个自定义的表格组件,即 table 组件 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 基于原生 table 标签的强语义 允许用户自定义表头.表体 可选是否具有边框 ...
- 11 - Vue3 UI Framework - Card 组件
卡片是非常常用也是非常重要的组件,特别是在移动端的众多应用场景中,随便打开一个手机 App ,您会发现充斥着各种各样的卡片. 所以,我们也来制作一个简易的 Card 组件 返回阅读列表点击 这里 需求 ...
- 00 - Vue3 UI Framework - 阅读辅助列表
阅读列表 01 - Vue3 UI Framework - 开始 02 - Vue3 UI Framework - 顶部边栏 03 - Vue3 UI Framework - 首页 04 - Vue3 ...
- 07- Vue3 UI Framework - Switch 组件
为了更好的提升用户体验,我们这里再做一个很常用的开关组件 switch 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 switch 组件应分为选中/未被选中,两种状态 可以通过 ...
- 04 - Vue3 UI Framework - 文档页
官网的首页做完了,接下来开始做官网的文档页 返回阅读列表点击 这里 路由设计 先想想我们需要文档页通向哪些地方,这里直接给出我的设计: 所属 子标题 跳转路径 文件名(*.vue) 指南 介绍 /do ...
- 01 - Vue3 UI Framework - 开始
写在前面 一年多没写过博客了,工作.生活逐渐磨平了棱角. 写代码容易,写博客难,坚持写高水平的技术博客更难. 技术控决定慢慢拾起这份坚持,用作技术学习的阶段性总结. 返回阅读列表点击 这里 开始 大前 ...
随机推荐
- 问题 C: A+B Problem II
题目描述 I have a very simple problem for you. Given two integers A and B, your job is to calculate the ...
- dotNET5的MVC页面传值方式总结
本文大致讲解mvc前后端的传值方式,包括control向view.view向control.以及action向action. 一.经典回顾 二.Controller向View传值 1. ViewBag ...
- Python基础(map/reduce)
from functools import reduce#reduce函数在python3的内建函数移除了,放入了functools模块 #map() list1 = [1,2,3,4,5,6,7,8 ...
- vue中使用echarts,地图上的涟漪特效大小设置
在使用echarts进行开发大屏时,使用到了地图这个组件 我们会根据返回的值来决定涟漪的大小 这时则使用 其它的value为返回的数组,一般格式为[经度,维度,值] 这样就能动态设置效果的大小了
- [luogu7078]贪吃蛇
结论:若$a_{n}-a_{1}\ge a_{2}$,那么一定会吃掉 证明:分类讨论,若$a_{n-1}$也吃掉了$a_{2}$,就说明$a_{n-1}$之后不会被吃掉,而$a_{n-1}-a_{2} ...
- [noi1760]SAM
建立SAM,求出每一个节点最左边的出现位置(即right集合中的最小元素,在树上dfs即可) 枚举左端点i和右端点j(保证j是最小的满足$s[i,j)$不是$s[0,i)$的子串),维护k表示$s[i ...
- SpringSecurity+Jwt遇到的bug
最近在使用springsecurity整合Jwt的时候,遇到了一Bug,卡住了很久,记录一下. 编写Jwt工具类JwtUtil,编写Jwt认证的核心过滤器JwtAuthenticationFilter ...
- 【AGC052A】
题目 \(有T组询问\) \(每次给一个n\) \(3个01串\),\(这三个串每个都有n个0\),\(n个1\),\(求一个2*n + 1的字符串\),\(使他成为S1+S1,S2+S2,S3+S3 ...
- perl中tr的用法(转载)
转载:http://blog.sina.com.cn/s/blog_4a0824490101hncz.html (1)/c表示把匹配不上的字符进行替换. $temp="AAAABCDEF&q ...
- 码上来战!探索“智”感生活,HMS Core线上Codelabs挑战赛第4期开始!
HMS Core线上Codelabs挑战赛第4期正式开始!我们向所有实践力超强.创新力满满的开发者发出邀请,用你的超级"码"力,解锁更多应用价值! 生活里,我们被手机"秒 ...