官网基本做好了,接下来开始做核心组件

返回阅读列表点击 这里

目录准备

在项目 src 目录下创建 lib 文件夹,用来存放所有的核心组件吧。然后再在 lib 文件夹下创建 Button.vue 文件。

您也可以进行结构化设计,比如,这里就不进行了。

|-lib
|-Button
|- Button.vue
|- Button.ts
|_ Button.scss

需求分析

惯例先行需求分析

  1. 多种类基础 Button,包含警告、成功、危险等
  2. 允许设置 Button 为禁用状态
  3. 不止有传统 Button,还可以有文字或链接形式
  4. 当处于加载中,Button 应当显示
  5. 有不同的尺寸可供选择
  6. 应当允许更换颜色
  7. 当鼠标放置于 Button 上、鼠标按下未松开、处于加载中等状态时,应当变更背景色
  8. 允许用户自定义 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

  1. 放置一个遮罩层,用于变色
  2. 放置一个”加载中”的动画,用于在加载中状态下显示
  3. 放置一个默认插槽,用于传递用户自定义的文本

然后为上述元素配置各自的 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; 才能消除

然后,我们使用 css3var() 语法,取得我们通过 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 组件的更多相关文章

  1. 06 - Vue3 UI Framework - Dialog 组件

    做完按钮之后,我们应该了解了遮罩层的概念,接下来我们来做 Dialog 组件! 返回阅读列表点击 这里 需求分析 默认是不可见的,在用户触发某个动作后变为可见 自带白板卡片,分为上中下三个区域,分别放 ...

  2. 10 - Vue3 UI Framework - Tabs 组件

    标签页是非常常用的组件,接下来我们来制作一个简单的 Tabs 组件 返回阅读列表点击 这里 需求分析 我们先做一个简单的需求分析 可以选择标签页排列的方向 选中的标签页应当有下划线高亮显示 切换选中时 ...

  3. 08 - Vue3 UI Framework - Input 组件

    接下来再做一个常用的组件 - input 组件 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 input 组件有两种类型,即 input 和 textarea 类型 当类型为 ...

  4. 09 - Vue3 UI Framework - Table 组件

    接下来做个自定义的表格组件,即 table 组件 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 基于原生 table 标签的强语义 允许用户自定义表头.表体 可选是否具有边框 ...

  5. 11 - Vue3 UI Framework - Card 组件

    卡片是非常常用也是非常重要的组件,特别是在移动端的众多应用场景中,随便打开一个手机 App ,您会发现充斥着各种各样的卡片. 所以,我们也来制作一个简易的 Card 组件 返回阅读列表点击 这里 需求 ...

  6. 00 - Vue3 UI Framework - 阅读辅助列表

    阅读列表 01 - Vue3 UI Framework - 开始 02 - Vue3 UI Framework - 顶部边栏 03 - Vue3 UI Framework - 首页 04 - Vue3 ...

  7. 07- Vue3 UI Framework - Switch 组件

    为了更好的提升用户体验,我们这里再做一个很常用的开关组件 switch 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 switch 组件应分为选中/未被选中,两种状态 可以通过 ...

  8. 04 - Vue3 UI Framework - 文档页

    官网的首页做完了,接下来开始做官网的文档页 返回阅读列表点击 这里 路由设计 先想想我们需要文档页通向哪些地方,这里直接给出我的设计: 所属 子标题 跳转路径 文件名(*.vue) 指南 介绍 /do ...

  9. 01 - Vue3 UI Framework - 开始

    写在前面 一年多没写过博客了,工作.生活逐渐磨平了棱角. 写代码容易,写博客难,坚持写高水平的技术博客更难. 技术控决定慢慢拾起这份坚持,用作技术学习的阶段性总结. 返回阅读列表点击 这里 开始 大前 ...

随机推荐

  1. JDK的第三个LTS版本JDK17来了

    目录 简介 JDK17中的新特性 语言上的新特性 核心库的优化 支持新的平台 预览特性 其他改动 总结 简介 2021年9月JDK17发布了,JDK17是最新的一个LTS版本.所谓LTS版本就是可以得 ...

  2. Django笔记&教程 6-4 forms进阶操作,重写forms方法

    Django 自学笔记兼学习教程第6章第4节--forms进阶操作,重写forms方法 点击查看教程总目录 1 - 重写clean方法 在本章第三节中,我们举了个注册学生账号的例子,里面我们使用模型来 ...

  3. vue.js学习与实战笔记(1)

    公司需要开发一个小型官网,个人决定放弃angular2,使用vue来进行开发,由于是培训出生,思想一时难以转变,所以只能从零开始,下面奉上学习笔记 vue.js主要参考官网进行学习与开发 由于vue不 ...

  4. <C#任务导引教程>练习一

    //1,定位显示ASCI码值为30到119的字符using System;class Program{    static void Main()    {        int i, n = 0;  ...

  5. [bzoj1146]网络管理

    发现是链上的问题,所以树链剖分发现要查询第k大,因为第k大不支持合并,所以要二分答案二分答案后相当于询问一些区间内大于某数的数个数,直接线段树套平衡树即可时间复杂度$o(nlog^{4}_n)$(跟$ ...

  6. Linux系统编程之匿名管道

    1.进程间通信介绍 1.1 进程通信的基本概念 在之前我们已经学习过进程地址空间.Linux 环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不 ...

  7. Codeforces 1208F - Bits And Pieces(高维前缀和)

    题面传送门 题意:求 \(\max\limits_{i<j<k}a_i|(a_j\&a_k)\). \(1\leq n \leq 10^6,1\leq a_i\leq 2\time ...

  8. 洛谷 P3644 [APIO2015]八邻旁之桥(对顶堆维护中位数)

    题面传送门 题意: 一条河将大地分为 \(A,B\) 两个部分.两部分均可视为一根数轴. 有 \(n\) 名工人,第 \(i\) 名的家在 \(x_i\) 区域的 \(a_i\) 位置,公司在 \(y ...

  9. DirectX12 3D 游戏开发与实战第九章内容(上)

    仅供个人学习使用,请勿转载. 9.纹理贴图 学习目标: 学习如何将局部纹理映射到网格三角形上 探究如何创建和启用纹理 学会如何通过纹理过滤来创建更加平滑的图像 探索如何使用寻址模式来进行多次纹理贴图 ...

  10. Docker Hadoop 配置常见错误及解决办法

    Docker Hadoop 配置常见错误及解决办法 问题1:wordcount运行卡住,hadoop 任务运行到running job就卡住了 INFO mapreduce.Job: Running ...