文章目录
一、组件库介绍
有兴趣的同学 可以先着手看源码,之前写的一系列开源组件库项目(有帮助的同学也帮忙点个star👍)
名称 | 官网 | github |
---|---|---|
tinkerbell-ui(vue2.0) | http://tinkerbell.top | https://github.com/hanbingxu82/tinkerbell-ui |
tinkerbell-ui(vue3.0) | — | https://github.com/hanbingxu82/tinkerbell-ui-next |
tinkerbell-ui(react-hook) | — | https://github.com/hanbingxu82/tinkerbell-ui-react |
二、Button组件流程介绍
提到 button 组件,这几乎可以说是一个组件库中的重中之重,基本上很多的时候我们都需要用到 button 来进行一系列的 dom 操作,时间执行,用户与浏览器之间进行交互不免得就少不了 button 按钮,那么我们先捋清楚一个思路这个 button 该怎么去写?
1、通用的事件行为是要有的,因为我们是自定义的组件,所以我们要考虑的一个问题,因为我们不能把所有的事件 都用 例如 props.onClick && props.onClick(evt) 这种方式去触发,所以我们去一个简单的方法直接解构所有的 props 传值,让其都放置在 我们的内置<button …restprop> 这种方式去进行一个子组件触发父组件行为,或者父组件传递子组件style这种。
2、因为我们上节课讲解了图标,那么这节课我们也把图标放置在 button 组件中,至于应用场景的话,我们可以放置静态图标或者放置一个动态的加载效果 这些我们都放置到对应的 button 组件中进行一个封装
3、默认常规的事件行为、属性控制等,我们也都加入到我们的 Button组件当中去
type = ‘default’, // 样式类型
icon = ‘’, // 图标样式
iconStyle, // icon 图标style
disabled, // 禁用效果
loading, // loading 加载效果
nativeType = ‘button’, // button 原生属性的type类型
size = ‘default’, // size 大小效果
plain, // 镂空 style 效果
round, // 圆角 style 效果
dashed, // 虚线 style 效果
transparent, // 是否为透明按钮
background, // 默认按钮是否带有拟物背景
loadingIcon, // 加载效果图标样式
textColor, // 文本颜色
…restprop //其余所有传递给 原生 button 的方法 属性
三、代码详解
3.1、index.tsx
// eslint-disable-next-line
import React from 'react'
import Icon from '../Icon'
import './index.scss'
var tinycolor = require('tinycolor2') // 颜色转换插件
const classnames = require('classnames') // classname 转换插件
// interface接口
interface Iprops {
type: string
disabled: boolean
loading: boolean
nativeType: any
size: string
plain: boolean
round: boolean
dashed: boolean
transparent: boolean
background: boolean
loadingIcon: string
iconStyle: any
icon: string
textColor: string
}
const Button = (props: any) => {
const {
type = 'default', // 样式类型
icon = '', // 图标样式
iconStyle, // icon 图标style
disabled, // 禁用效果
loading, // loading 加载效果
nativeType = 'button', // button 原生属性的type类型
size = 'default', // size 大小效果
plain, // 镂空 style 效果
round, // 圆角 style 效果
dashed, // 虚线 style 效果
transparent, // 是否为透明按钮
background, // 默认按钮是否带有拟物背景
loadingIcon, // 加载效果图标样式
textColor, // 文本颜色
...restprop //其余所有传递给 原生 button 的方法 属性
}: Iprops = props
// icon图标style
function iconStyles() {
return {
...textStyle(),
...iconStyle
}
}
// 默认 文本样式给与的颜色
function colorMap() {
return {
primary: '#1089ff',
success: '#52c41a',
info: '#35495E',
warning: '#fea638',
danger: '#ff4d4f'
}
}
// 点击事件触发父行为
function handleClick(evt: any) {
props.onClick && props.onClick(evt)
}
// 鼠标进入触发父行为
function handMouseEnter(evt: any) {
props.onMouseEnter && props.onMouseEnter(evt)
}
// 鼠标离开触发父行为
function handMouseLeave(evt: any) {
props.onMouseLeave && props.onMouseLeave(evt)
}
// 触发获取焦点事件
function handFocus(evt: any) {
props.onFocus && props.onFocus(evt)
}
// text 文本颜色
function textStyle() {
let color = textColor
? colorMap()[textColor]
? colorMap()[textColor]
: textColor
: null
if (color) {
return {
color: disabled ? tinycolor(color).lighten(15).toString() : color
}
}
return {}
}
// 判断传递的组件是否为 文本 按钮 如果不是
if (type !== 'text') {
return (
<button
{...restprop}
onClick={handleClick}
onMouseEnter={handMouseEnter}
onMouseLeave={handMouseLeave}
onFocus={handFocus}
disabled={disabled || loading}
type={nativeType}
className={
[
'tb-button',
'tb-button--' + type,
'tb-button--' + size,
classnames({
'is-disabled': disabled,
'is-loading': loading,
'is-plain': plain,
'is-round': round,
'is-dashed': dashed,
'is-transparent': transparent,
'is-background': background
})
].join(' ') +
' ' +
props.className
}
>
{/* 判断有没有loading加载 */}
{loading && (
<span className={'btn-icon-loading'}>
<Icon
className='button-loading icon-is-rotating'
name={loadingIcon ? loadingIcon : 'icon-loading'}
style={iconStyles()}
/>
</span>
)}
{/* 判断有没有静态图标 */}
{icon && !loading && (
<i className={['iconfont', icon].join(' ')} style={iconStyles()}></i>
)}
{props.children && <span style={textStyle()}>{props.children}</span>}
</button>
)
} else {
// 如果是文本按钮
return (
<button
{...restprop}
onClick={handleClick}
onMouseEnter={handMouseEnter}
onMouseLeave={handMouseLeave}
onFocus={handFocus}
disabled={disabled || loading}
type={nativeType}
className={
[
'tb-button',
'tb-button--' + type,
classnames({ 'is-disabled': disabled, 'is-loading': loading })
].join(' ') +
' ' +
props.className
}
>
{/* 判断图标 在这里就没必要给加载判断了 */}
{icon && !loading && (
<i className={['iconfont', icon].join(' ')} style={iconStyles()}></i>
)}
{props.children && <span style={textStyle()}>{props.children}</span>}
</button>
)
}
}
export default Button
3.2、index.scss
@import '../../style/variables.scss';
.tb-button {
position: relative;
display: inline-block;
vertical-align: middle;
height: $default-height;
line-height: $default-height - 2;
white-space: nowrap;
cursor: pointer;
background: $color-white;
border: $border-base;
color: $color-text-default;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: $animation-duration-base;
user-select: none;
padding: 0 15px;
font-size: $base-font-size;
border-radius: $border-base-radius;
.iconfont {
vertical-align: -1px;
+span {
margin-left: 4px;
}
}
&-loading {
font-size: 14px;
margin-right: 5px;
}
&:hover,
&:focus {
color: $color-primary;
border-color: $color-primary;
}
&:active {
color: $color-primary-active;
border-color: $color-primary-active;
}
&.is-round {
border-radius: 20px;
}
&.is-transparent {
background: transparent;
border-color: #fff;
color: #fff;
&:hover {
color: $color-primary;
border-color: $color-primary;
}
&:active {
color: $color-primary-active;
border-color: $color-primary-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
background: transparent;
cursor: not-allowed;
color: #fff;
}
}
&.is-dashed {
&:hover {
color: $color-primary;
border-color: $color-primary;
}
&:active {
color: $color-primary-active;
border-color: $color-primary-active;
}
}
&.is-background {
background-image: -webkit-gradient(linear, left bottom, left top, from(#f5f5f5), to(#fff));
background-image: linear-gradient(0deg, #f5f5f5, #fff);
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
color: #c0c4cc;
cursor: not-allowed;
background-image: none;
background: #f5f5f5;
border-color: #d9d9d9;
}
}
&.is-loading {
pointer-events: none;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
color: #c0c4cc;
cursor: not-allowed;
background-image: none;
background-color: #fff;
border-color: #ebeef5;
}
}
.tb-button--large {
height: $large-height;
line-height: $large-height - 2;
padding: 0 14px;
font-size: $header-font-size;
&.is-round {
padding: 0 14px;
}
}
.tb-button--small {
height: $small-height;
line-height: $small-height - 2;
padding: 0 11px;
&.is-round {
padding: 0 11px;
}
}
.tb-button--mini {
height: $mini-height;
line-height: $mini-height - 2;
padding: 0 7px;
&.is-round {
padding: 0 10px;
}
}
.tb-button--primary {
color: $color-white;
background-color: $color-primary;
border-color: $color-primary;
background-image: none;
&:hover,
&:focus {
background: $color-primary-light1;
border-color: $color-primary-light1;
color: #fff;
}
&:active {
background: $color-primary-active;
border-color: $color-primary-active;
}
&.is-transparent {
border-color: $color-primary;
color: $color-primary;
background-color: transparent;
&:hover {
border-color: $color-primary-light1;
color: $color-primary;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-primary-active;
border-color: $color-primary-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
border-color: $color-primary-light2;
color: $color-primary-light2;
}
}
&.is-plain {
color: $color-primary;
background: $color-primary-light5;
border-color: $color-primary-light3;
&:hover,
&:focus {
border-color: $color-primary-light2;
}
&:active {
color: $color-primary-active;
border-color: $color-primary-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
cursor: not-allowed;
color: $color-primary-light2;
background-color: $color-primary-light5;
border-color: $color-primary-light3;
}
}
&.is-dashed {
background: $color-white;
color: $color-primary;
&:hover {
border-color: $color-primary-light1;
color: $color-primary;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-primary-active;
border-color: $color-primary-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
background: $color-white;
color: $color-primary-light2;
}
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
color: $color-white;
background-color: $color-primary-light2;
border-color: $color-primary-light2;
}
}
.tb-button--success {
color: #fff;
background-color: $color-success;
border-color: $color-success;
background-image: none;
&:hover,
&:focus {
background: $color-success-light1;
border-color: $color-success-light1;
color: #fff;
}
&:active {
background: $color-success-active;
border-color: $color-success-active;
}
&.is-transparent {
border-color: $color-success;
color: $color-success;
background-color: transparent;
&:hover {
border-color: $color-success-light1;
color: $color-success;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-success-active;
border-color: $color-success-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
border-color: $color-success-light2;
color: $color-success-light2;
}
}
&.is-plain {
color: $color-success;
background: $color-success-light5;
border-color: $color-success-light3;
&:hover,
&:focus {
border-color: $color-success-light2;
}
&:active {
color: $color-success-active;
border-color: $color-success-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
cursor: not-allowed;
color: $color-success-light2;
background-color: $color-success-light5;
border-color: $color-success-light3;
}
}
&.is-dashed {
background: $color-white;
color: $color-success;
&:hover {
border-color: $color-success-light1;
color: $color-success;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-success-active;
border-color: $color-success-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
background: $color-white;
color: $color-success-light2;
}
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
color: $color-white;
background-color: $color-success-light2;
border-color: $color-success-light2;
}
}
.tb-button--info {
color: #fff;
background-color: $color-info;
border-color: $color-info;
background-image: none;
&:hover,
&:focus {
background: $color-info-light1;
border-color: $color-info-light1;
color: #fff;
}
&:active {
background: $color-info-active;
border-color: $color-info-active;
}
&.is-transparent {
border-color: $color-info;
color: $color-info;
background-color: transparent;
&:hover {
border-color: $color-info-light1;
color: $color-info;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-info-active;
border-color: $color-info-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
border-color: $color-info-light2;
color: $color-info-light2;
}
}
&.is-plain {
color: $color-info;
background: $color-info-light5;
border-color: $color-info-light3;
&:hover,
&:focus {
border-color: $color-info-light2;
}
&:active {
color: $color-info-active;
border-color: $color-info-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
cursor: not-allowed;
color: $color-info-light2;
background-color: $color-info-light5;
border-color: $color-info-light3;
}
}
&.is-dashed {
background: $color-white;
color: $color-info;
&:hover {
border-color: $color-info-light1;
color: $color-info;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-info-active;
border-color: $color-info-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
background: $color-white;
color: $color-info-light2;
}
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
color: $color-white;
background-color: $color-info-light2;
border-color: $color-info-light2;
}
}
.tb-button--warning {
color: #fff;
background-color: $color-warning;
border-color: $color-warning;
background-image: none;
&:hover,
&:focus {
background: $color-warning-light1;
border-color: $color-warning-light1;
color: #fff;
}
&:active {
background: $color-warning-active;
border-color: $color-warning-active;
}
&.is-transparent {
border-color: $color-warning;
color: $color-warning;
background-color: transparent;
&:hover {
border-color: $color-warning-light1;
color: $color-warning;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-warning-active;
border-color: $color-warning-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
border-color: $color-warning-light2;
color: $color-warning-light2;
}
}
&.is-plain {
color: $color-warning;
background: $color-warning-light5;
border-color: $color-warning-light3;
&:hover,
&:focus {
border-color: $color-warning-light2;
}
&:active {
color: $color-warning-active;
border-color: $color-warning-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
cursor: not-allowed;
color: $color-warning-light2;
background-color: $color-warning-light5;
border-color: $color-warning-light3;
}
}
&.is-dashed {
background: $color-white;
color: $color-warning;
&:hover {
border-color: $color-warning-light1;
color: $color-warning;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-warning-active;
border-color: $color-warning-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
background: $color-white;
color: $color-warning-light2;
}
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
color: $color-white;
background-color: $color-warning-light2;
border-color: $color-warning-light2;
}
}
.tb-button--danger {
color: #fff;
background-color: $color-danger;
border-color: $color-danger;
background-image: none;
&:hover,
&:focus {
background: $color-danger-light1;
border-color: $color-danger-light1;
color: #fff;
}
&:active {
background: $color-danger-active;
border-color: $color-danger-active;
}
&.is-transparent {
border-color: $color-danger;
color: $color-danger;
background-color: transparent;
&:hover {
border-color: $color-danger-light1;
color: $color-danger;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-danger-active;
border-color: $color-danger-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
border-color: $color-danger-light2;
color: $color-danger-light2;
}
}
&.is-plain {
color: $color-danger;
background: $color-danger-light5;
border-color: $color-danger-light3;
&:hover,
&:focus {
border-color: $color-danger-light2;
}
&:active {
color: $color-danger-active;
border-color: $color-danger-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
cursor: not-allowed;
color: $color-danger-light2;
background-color: $color-danger-light5;
border-color: $color-danger-light3;
}
}
&.is-dashed {
background: $color-white;
color: $color-danger;
&:hover {
border-color: $color-danger-light1;
color: $color-danger;
background-color: rgba(245, 249, 254, .5);
}
&:active {
color: $color-danger-active;
border-color: $color-danger-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
background: $color-white;
color: $color-danger-light2;
}
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover,
&.is-loading {
cursor: not-allowed;
color: $color-white;
background-color: $color-danger-light2;
border-color: $color-danger-light2;
}
}
.tb-button--text {
border-color: transparent;
color: $color-primary;
background: transparent;
background-image: none;
padding: 0;
height: auto;
line-height: inherit;
&:focus,
&:hover {
color: $color-primary-light1;
border-color: transparent;
background-color: transparent;
box-shadow: none;
}
&:active {
color: $color-primary-active;
}
&.is-disabled,
&.is-disabled:focus,
&.is-disabled:hover {
cursor: not-allowed;
background-color: transparent;
border-color: transparent;
color: $color-primary-light3;
}
}
.tb-button--dashed,
.is-dashed {
border-style: dashed;
}
// button-group
.tb-button-group {
display: inline-block;
vertical-align: middle;
&>.tb-button {
float: left;
position: relative;
}
.tb-button {
z-index: 0;
&:hover {
z-index: 1;
}
&:active {
z-index: 1;
outline: none;
}
}
.tb-button+.tb-button {
margin-left: -1px;
}
&>.tb-button:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
&>.tb-button:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
&>.tb-button:not(:first-child):not(:last-child) {
border-radius: 0;
}
.tb-button--primary:first-child,
.tb-button--info:first-child,
.tb-button--success:first-child,
.tb-button--warning:first-child,
.tb-button--danger:first-child {
border-right-color: hsla(0, 0%, 100%, .5);
}
.tb-button--primary:last-child .tb-button--info:last-child,
.tb-button--success:last-child,
.tb-button--warning:last-child,
.tb-button--danger:last-child {
border-left-color: hsla(0, 0%, 100%, .5);
}
.tb-button--primary:not(:first-child):not(:last-child),
.tb-button--info:not(:first-child):not(:last-child),
.tb-button--success:not(:first-child):not(:last-child),
.tb-button--warning:not(:first-child):not(:last-child),
.tb-button--danger:not(:first-child):not(:last-child) {
border-left-color: hsla(0, 0%, 100%, .5);
border-right-color: hsla(0, 0%, 100%, .5);
}
}
.tb-button+.tb-button {
margin-left: 8px;
}
@keyframes rotating {
from {
transform: rotate(0)
}
to {
transform: rotate(360deg)
}
}
.btn-icon-loading {
display: inline-block;
animation: rotating 2s linear infinite
}
3.3、variables.scss(这里的文本样式是参考的 bin-ui )
// $font-path : './fonts'
/* Color
-------------------------- */
$color-white : #FFFFFF;
$color-white-light : rgba(255, 255, 255, 0.65);
$color-white-light2 : rgba(255, 255, 255, 0.35);
$color-primary : #1089ff;
$color-primary-light1 : mix(#FFFFFF, $color-primary, 20%);
$color-primary-light2 : mix(#FFFFFF, $color-primary, 40%);
$color-primary-light3 : mix(#FFFFFF, $color-primary, 60%);
$color-primary-light4 : mix(#FFFFFF, $color-primary, 80%);
$color-primary-light5 : mix(#FFFFFF, $color-primary, 90%);
$color-primary-light6 : mix(#FFFFFF, $color-primary, 95%);
$color-primary-active : mix(#000000, $color-primary, 10%);
$color-success :#52c41a;
$color-success-light1 : mix(#FFFFFF, $color-success, 20%);
$color-success-light2 : mix(#FFFFFF, $color-success, 40%);
$color-success-light3 : mix(#FFFFFF, $color-success, 60%);
$color-success-light4 : mix(#FFFFFF, $color-success, 80%);
$color-success-light5 : mix(#FFFFFF, $color-success, 90%);
$color-success-light6 : mix(#FFFFFF, $color-success, 95%);
$color-success-active : mix(#000000, $color-success, 10%);
$color-info : #35495E;
$color-info-light1 : mix(#FFFFFF, $color-info, 20%);
$color-info-light2 : mix(#FFFFFF, $color-info, 40%);
$color-info-light3 : mix(#FFFFFF, $color-info, 60%);
$color-info-light4 : mix(#FFFFFF, $color-info, 80%);
$color-info-light5 : mix(#FFFFFF, $color-info, 90%);
$color-info-light6 : mix(#FFFFFF, $color-info, 95%);
$color-info-active : mix(#000000, $color-info, 10%);
$color-warning : #fea638;
$color-warning-light1 : mix(#FFFFFF, $color-warning, 20%);
$color-warning-light2 : mix(#FFFFFF, $color-warning, 40%);
$color-warning-light3 : mix(#FFFFFF, $color-warning, 60%);
$color-warning-light4 : mix(#FFFFFF, $color-warning, 80%);
$color-warning-light5 : mix(#FFFFFF, $color-warning, 90%);
$color-warning-light6 : mix(#FFFFFF, $color-warning, 95%);
$color-warning-active : mix(#000000, $color-warning, 10%);
$color-danger : #ff4d4f;
$color-danger-light1 : mix(#FFFFFF, $color-danger, 20%);
$color-danger-light2 : mix(#FFFFFF, $color-danger, 40%);
$color-danger-light3 : mix(#FFFFFF, $color-danger, 60%);
$color-danger-light4 : mix(#FFFFFF, $color-danger, 80%);
$color-danger-light5 : mix(#FFFFFF, $color-danger, 90%);
$color-danger-light6 : mix(#FFFFFF, $color-danger, 95%);
$color-danger-active : mix(#000000, $color-danger, 10%);
/* text-color
-------------------------- */
$color-text-primary : rgba(0, 0, 0, .85);
$color-text-default : rgba(0, 0, 0, .65);
$color-text-secondary : rgba(0, 0, 0, .45);
$color-text-disabled : rgba(0, 0, 0, .25);
$color-text-placeholder : #C0C4CC;
$btn-disable-color : #c5c8ce;
$color-disabled-bg:rgb(245, 245, 245);
$color-disabled-border:rgb(217, 217, 217);
/* bg-color
-------------------------- */
$color-bg-fa : #fafafa;
$color-select-hover : #f5f5f5;
$color-effect-shadow : alpha($color-primary);
$color-input-shadow : alpha($color-primary);
$color-input-error-shadow : alpha($color-danger);
/* border
-------------------------- */
$border-color-base : #d9d9d9;
$border-color-light : #f0f0f0;
$border-base : 1px solid $border-color-base;
$border-width:1px;
$border-base-light : 1px solid $border-color-light;
$border-table : 1px solid #e8eaec;
$border-table-color : #e8eaec;
/* radius font-size
-------------------------- */
$border-base-radius : 2px;
$base-font-size : 14px;
$header-font-size : 16px;
/* height
-------------------------- */
$large-height : 36px;
$default-height : 32px;
$small-height : 28px;
$mini-height : 24px;
$base-line-height : 1.5715;
$animation-duration-slow : 0.3s;
$animation-duration-base : 0.2s;
$animation-duration-fast : 0.1s;
// placeholder
$placeholder-color : #c0c4cc;
四、效果呈现
至此效果实现
当然后续我这边 react 官网也会同步文章进行,也请大家持续关注博主
结语
✨ 每天创作一点点
✨ 开心快乐一整天
✨ 点赞关注加收藏
✨ 美好一天又一天
铁铁们 感谢支持 我需要你们的三连 👍👍👍