introduce
The most common action button, Button is the browser’s own action button, but in order to unify the style, we will smooth out the browser style gap, incidentally add some new functions.
The functionality you want to implement
function | introduce |
---|---|
type | Primary/success/warning/danger/info/text |
disabled | It is prohibited to use |
size | 4 sizes, Large, medium, Small, mini |
icon | Settable icon |
round | Rounded button or not |
circle | Circular button or not |
loading | Loading state |
Function implementation
1. Basic functions
Create a new “button. SCSS” folder under “button.vue” and “index.js” SRC /styles/ “SRC /styles/index.scss”
// button.vue
<template>
<button class="my-button my-button-primary">
<slot>button</slot>
</button>
</template>
<script>
export default {
name: 'Button',
data () {
return{}}},</script>
Copy the code
// button/index.js
import Button from './button.vue'
export default Button
Copy the code
// styles/button.scss
@charset "UTF-8";
@import "common/var";
@import "mixins/mixins";
@include b(button) {
height: 36px;
font-size: $--font-size-medium;
color: #fff;
border-radius: 4px;
outline: none;
border: 1px solid transparent;
padding: 0 10px;
cursor: pointer;
&-primary {
background-color: $--color-primary;
// focus,hover, background color becomes lighter
&:focus,
&:hover {
background-color: rgba($--color-primary, 0.7);
}
&:active {
// When active, the background color becomes lighter and is distinguished from focus and hover
background-color: rgba($--color-primary, 0.9); }}}Copy the code
// styles/index.scss
@import "button";
Copy the code
2. Type type
Button types are distinguished mainly by background color. So just set class according to type. A total of six types is designed, the primary (default), the info, success, warning, error, and the text.
// button.vue
<template>
<button class="my-button" :class="{[`my-button-${type}`]: true}">
<slot>button</slot>
</button>
</template>
<script>
// the utility function is used to determine whether the value passed meets the criteria
import { oneOf } from '.. /.. /utils/assist'
export default {
name: 'Button',
data () {
return{}},props: {
type: {
validator(value) {
return oneOf(value, [
'primary'.'info'.'success'.'warning'.'text'.'error',}]),type: String.default: 'primary',,}}}</script>
Copy the code
Then there are the styles for the different types
// button.scss --
&-info {
background-color: $--color-info;
border-color: #ddd;
color: $--font-color-main;
&:focus,
&:hover {
color: rgba($--font-color-main, 0.7);
}
&:active {
color: rgba($--font-color-main, 0.9);
}
}
&-success {
background-color: $--color-success;
border-color: $--color-success;
&:focus,
&:hover {
background-color: rgba($--color-success, 0.7);
}
&:active {
background-color: rgba($--color-success, 0.9);
}
}
&-warning {
background-color: $--color-warning;
border-color: $--color-warning;
&:focus,
&:hover {
background-color: rgba($--color-warning, 0.7);
}
&:active {
background-color: rgba($--color-warning, 0.9);
}
}
&-text {
background-color: $--color-text;
border-color: $--color-text;
color: $--color-primary;
&:focus,
&:hover {
color: rgba($--color-primary, 0.7);
}
&:active {
color: rgba($--color-primary, 0.9);
}
}
&-error {
background-color: $--color-error;
border-color: $--color-error;
&:focus,
&:hover {
background-color: rgba($--color-error, 0.7);
}
&:active {
background-color: rgba($--color-error, 0.9); }}Copy the code
3. The disabled are prohibited
The logic is simple, using the button tag’s native Disabled property. Basically write the style corresponding to the disabled state
<template>
<button
class="my-button"
:disabled="disabled"
:class="{ [`my-button-${type}`]: true, [`my-button-${type}-disabled`]: disabled, }"
@click="handleClick"
>
<slot>button</slot>
</button>
</template>
<script>
// the utility function is used to determine whether the value passed meets the criteria
import { oneOf } from '.. /.. /utils/assist'
export default {
name: 'Button'.data() {
return{}},props: {
type: {
validator(value) {
return oneOf(value, [
'primary'.'info'.'success'.'warning'.'text'.'error',}]),type: String.default: 'primary',},disabled: {
type: Boolean.default: false,}},methods: {
handleClick(event) {
console.log('Button clicked', event)
this.$emit('click', event)
},
},
}
</script>
Copy the code
// button.scss omits some code
&-primary {
background-color: $--color-primary;
border-color: $--color-primary;
// focus,hover, background color becomes lighter
&:focus,
&:hover {
background-color: rgba($--color-primary, 0.7);
border-color: rgba($--color-primary, 0.7);
}
&:active {
// When active, the background color becomes lighter and is distinguished from focus and hover
background-color: rgba($--color-primary, 0.9);
border-color: rgba($--color-primary, 0.9);
}
// When disabled, it is disabled
&-disabled {
cursor: not-allowed;
background-color: rgba($--color-primary, 0.5);
border-color: rgba($--color-primary, 0.5);
&:focus,
&:hover,
&:active {
background-color: rgba($--color-primary, 0.5);
border-color: rgba($--color-primary, 0.5); }}}Copy the code
Set the disabled style according to type. In the disabled state, the mouse style changes to not-allowed, and the background color increases opacity by 50%. The above style code is primary, and the other five types are the same.
4. The size of the size
Four sizes are set: Large, Medium (default), small, and mini. Sizing is also done by binding class.
// button.vue omits some code
<template>
<button
class="my-button"
:disabled="disabled"
:class="{ [`my-button-${type}`]: true, [`my-button-${type}-disabled`]: disabled, [`my-button-size-${size}`]: true }"
@click="handleClick"
>
<slot>button</slot>
</button>
</template>
<script>
export default{...props: {
size: {
validator(value) {
return oneOf(value, [
'large'.'medium'.'small'.'mini'])},type: String.default: 'medium',}}}</script>
Copy the code
// button.scss omits some code
// Here are the styles related to size. &-size { &-large {height: 40px;
line-height: 40px;
}
&-medium {
height: 36px;
line-height: 36px;
}
&-small {
height: 32px;
line-height: 32px;
font-size: $--font-size-small;
}
&-mini {
height: 28px; line-height: 28px; font-size: $--font-size-small; }}Copy the code
5. Set the icon icon
The use of ICONS refer to the Font class reference method of IconFONT, and ICONS can be updated as long as the icon project library is maintained. Select the icon from iconfont to add to the project, then download it locally.
Unzip the downloaded file to the SRC /styles/font directory and reference it in styles/index.scss.
// styles/index.scss
@import "./font/iconfont.css";
Copy the code
< I class=”iconfont icon-xxx” />
// button.vue omits some code
<template>
<button
class="my-button"
:disabled="disabled"
:class="{ [`my-button-${type}`]: true, [`my-button-${type}-disabled`]: disabled, [`my-button-size-${size}`]: true }"
@click="handleClick"
>
<i :class="['iconfont', `${icon}`]"></i>
<slot></slot>
</button>
</template>
<script>
export default{.../ / icon
icon: {
type: String}... }</script>
Copy the code
6. Rounded button
The function is simple. Set border-radius.
// button.vue omits some code
<template>
<button
class="my-button"
:disabled="disabled"
:class="{ [`my-button-${type}`]: true, [`my-button-${type}-disabled`]: disabled, [`my-button-size-${size}`]: true, [`my-button-size-${size}-round`]: round }"
@click="handleClick"
>
<i :class="['iconfont', `${icon}`]"></i>
<slot></slot>
</button>
</template>
<script>
export default{.../ / icon
round: {
type: Boolean.default: false}... }</script>
Copy the code
// button.scss omits some code
&-size {
&-large {
height: 40px;
line-height: 40px;
&-round {
border-radius: 20px;
}
}
&-medium {
height: 36px;
line-height: 36px;
&-round {
border-radius: 18px;
}
}
&-small {
height: 32px;
line-height: 32px;
font-size: $--font-size-small;
&-round {
border-radius: 16px;
}
}
&-mini {
height: 28px; line-height: 28px; font-size: $--font-size-small; &-round { border-radius: 14px; }}}Copy the code
7. Circular button
The implementation roadmap is the same as that for the rounded corner button. Set the border-radius to 50%. Here we need to adjust the min-width and padding so that width is equal to height.
// button.vue omits some code
<template>
<button
class="my-button"
:disabled="disabled"
:class="{ [`my-button-${type}`]: true, [`my-button-${type}-disabled`]: disabled, [`my-button-size-${size}`]: true, [`my-button-size-${size}-round`]: round, [`my-button-size-${size}-circle`]: circle }"
@click="handleClick"
>
<i :class="['iconfont', `${icon}`]"></i>
<slot></slot>
</button>
</template>
<script>
export default{.../ / icon
circle: {
type: Boolean.default: false}... }</script>
Copy the code
// button.scss omits some code. &-size { &-large {height: 40px;
line-height: 40px;
&-round {
border-radius: 20px;
}
&-circle {
min-width: 40px;
border-radius: 50%;
}
}
&-medium {
height: 36px;
line-height: 36px;
&-round {
border-radius: 18px;
}
&-circle {
min-width: 36px;
border-radius: 50%;
}
}
&-small {
height: 32px;
line-height: 32px;
font-size: $--font-size-small;
&-round {
border-radius: 16px;
}
&-circle {
padding: 0 5px;
min-width: 32px;
border-radius: 50%;
}
}
&-mini {
height: 28px;
line-height: 28px;
font-size: $--font-size-small;
&-round {
border-radius: 14px;
}
&-circle {
padding: 0 5px;
min-width: 28px;
border-radius: 50%; }}}Copy the code
8. Loading
button
Add an internal oneloading
Icon, passed in by the userloading
Parameter control display hide. Note and provide to the usericon
Make a toggle and makeloading
Icon andicon
The ICONS of parameters are mutually exclusive.loading
State, the button is disabled, thereforedisabled
Properties byloading
anddisabled
Make joint decisions.- Construct one out of pseudo-elements
layer
Covering thebutton
Above, at the same timebutton
thepointer-events
Set tonone
“, so that the button can not be clicked.
// button.vue
<template>
<button
class="my-button"
:disabled="disabled || loading"
:class="{ [`my-button-${type}`]: true, [`my-button-${type}-disabled`]: disabled, [`my-button-size-${size}`]: true, [`my-button-size-${size}-round`]: round, [`my-button-size-${size}-circle`]: circle, [`my-button-loading-layer`]: loading }"
@click="handleClick"
>
<i
class="iconfont icon-loading"
:class="{ [`my-button-loading`]: true }"
v-if="loading"
/>
<i :class="['iconfont', `${icon}`]" v-if=! "" loading"></i>
<slot></slot>
</button>
</template>
<script>
// the utility function is used to determine whether the value passed meets the criteria
import { oneOf } from '.. /.. /utils/assist'
export default {
name: 'Button'.data() {
return{}},props: {
type: {
validator(value) {
return oneOf(value, [
'primary'.'info'.'success'.'warning'.'text'.'error',}]),type: String.default: 'primary',},disabled: {
type: Boolean.default: false,},size: {
validator(value) {
return oneOf(value, [
'large'.'medium'.'small'.'mini'])},type: String.default: 'medium',},/ / icon
icon: {
type: String
},
// Round button
round: {
type: Boolean.default: false
},
// Round button
circle: {
type: Boolean.default: false
},
loading: {
type: Boolean.default: false}},methods: {
handleClick(event) {
console.log('Button clicked', event)
this.$emit('click', event)
},
},
}
</script>
Copy the code
// button.scss omits some code
&-loading-layer {
pointer-events: none;
&::before {
pointer-events: none;
content: ' ';
position: absolute;
left: -1px;
top: -1px;
right: -1px;
bottom: -1px;
border-radius: inherit;
background-color: rgba(255.255.255.0.4); }}Copy the code
conclusion
The above is the first vUE knowledge review UI components, to introduce the most common component Button implementation process, the use of VUE related knowledge has parent-child component communication, class and style binding, slot slot and so on. These are the basic knowledge, not difficult, but more about the processing of CSS, such as the weight design of CSS when overwriting styles, and the use of false elements to overwrite the loading function so that it cannot be clicked, etc.
Scaffolding please refer to the first: juejin.cn/post/701798… Oversnail.github. IO/over-snail-… Git address: github.com/overSnail/o…
Involve knowledge points and reference articles
1. (Vue) : class and style binding 2. (Vue) : prop parent component parameter transfer 3. (Vue) : slot slot 4