。故事前景:之前没有封装过公共组件到某个组件库的经验,此次是从零开始,我尽量写的详细一些,开始还抱着一些担忧,后来发现这个就像我们平时写业务一样,不是很难,难的是封装的组件做到让别人挑剔不起来。
好了,话不多说,咱们开始今天的话题。
开始之前有些什么:有一个老大搭建好的组件库项目,是用的storybook去搭建的,下面我把老大搭建的框架用到的开发依赖跟生产依赖截图出来
然后项目的目录
然后这些是开始就有的
然后有同事已经在她的分支上封装好了一个组件,input组件,我参考了一下她的封装,并且我封装的Button组件有大致给出业务场景,还有设计文档,我截图出来
就这样,带着实现这些功能的目的我开始了组件封装
我就是引用组件的方式,来传参实现控制这些功能就算完成任务,下面来分享一下我写的代码,小二,上代码~
```
import React, { useState } from "react";
import styled, { css } from "styled-components";
import { rem } from "@utils/UtilsFunc";
const Wrapper = styled.button`
width: ${(props) => (props.isInline === true ? "" : rem(250))};
height: ${(props) => (props.size === "small" ? rem(28) : rem(40))};
margin: 0 auto;
border: none;
font-size: 16px;
color: #ffffff;
border-radius: ${rem(4)};
background-color: #ff5b5b;
padding: 0 ${rem(16)};
${(props) =>
props.shape &&
css`
border-radius: ${props.shape === "square"
? 0
: props.shape === "circle"
? rem(20)
: rem(4)};
`};
${(props) =>
props.type &&
css`
background: ${props.type === "normal"
? "linear-gradient(137deg, #ff5b5b 0%, #db0113 100%)"
: "transparent"};
border: 1px solid ${props.type === "normal" ? "none" : "#FF5B5B"};
color: ${props.type === "normal" ? "#FFFFFF" : "#FF5B5B"};
`};
${(props) =>
props.isShortClick &&
css`
background: ${props.type === "normal"
? "rgba(255, 255, 255, 0.372)"
: "linear-gradient(137deg, #f70000 0%, #f70000 100%);"};
color: ${props.type === "normal" ? "rgb(242, 145, 145)" : "#fc9d9d"};
`};
${(props) =>
css`
display: ${props.isInline === true ? "inline-block" : "block"};
`};
${(props) =>
props.disabled &&
props.isBgGrey &&
css`
background: ${props.type === "normal" ? "#E09896" : "transparent"};
`}
${(props) =>
(props.disabled === false || props.isBgGrey === false) &&
css`
background: ${props.type === "normal"
? "linear-gradient(137deg, #ff5b5b 0%, #db0113 100%)"
: "transparent"};
`}
.button-disabled {
${(props) =>
props.type &&
css`
color: ${props.type === "normal"
? "rgba(255, 255, 255, 0.6)"
: "#E09896"};
`};
opacity: 0.4;
}
`;
const Button = (props) => {
const {
shape,
type,
text,
disabled,
onClick,
isBgGrey,
isInline,
size,
style,
throttleTime
} = props;
const [isShortClick, setIsShortClick] = useState(false);
const [isThrottle, setIsThrottle] = useState(false);
const _onClick = () => {
if (disabled === true) {
return;
}
if (isThrottle === true) {
return;
}
console.log("click the button");
setIsShortClick(true);
setIsThrottle(true);
onClick();
setTimeout(() => {
setIsShortClick(false);
}, 100);
// 节流处理
setTimeout(() => {
setIsThrottle(false);
}, throttleTime);
};
return (
<Wrapper
shape={shape}
type={type}
isInline={isInline}
size={size}
isShortClick={isShortClick}
onClick={_onClick}
style={style}
disabled={disabled}
isBgGrey={isBgGrey}
>
<span className={disabled && isBgGrey ? "button-disabled" : ""}>
{text}
</span>
</Wrapper>
);
};
Button.defaultProps = {
type: "normal",
shape: "default",
text: "this is a button",
disabled: false,
onClick: () => {},
isBgGrey: true,
isInline: false,
size: "small",
throttleTime: 500,
style: {}
};
export default Button;
```
仔细看其实用到的东西就是三个
1.Button.defaultProps
2. styled-components的使用
3.${}让其在css里面可以写js用这些来灵活的使用外部组件传进来的参数控制整个组件的一个状态
其实到上面那些代码这个组件已经封装好了,那么还有就是如何像antd mobile或者vant UI那么去展示呢
看到右边的control没有,修改那个就能更改模拟机上面显示的效果,那么这个就是重点,也是难点
笔者开头已经说过,这个架构是老大(架构师)搭建起来的,用于收集加工业务组件,提高开发效率,让我们不用繁忙于业务,高效的完成业务开发
在这里附上组件库搭建用到的技术(storybook)官网地址:https://storybook.js.org/tutorials/
再来说有了这个架构以及有了刚才封装的组件如何在页面中给它展示出来
如图除了guideDocAssets(里面放了一些图片)存放静态资源的地方,我们之所以能看到页面上的那个类似antd mobile里面看到的那些效果
下面我付出源码标注一下意思
```
import React from "react";
import Button from "@components/Button";
import "lib-flexible";
export default {
title: "TCLPH/Component/Button",
component: Button,
parameters: {
viewport: {
defaultViewport: "iphone6"
},
layout: "padded" // 'padded' | 'centered' | 'fullscreen',
},
argTypes: {
type: {
defaultValue: "normal",
description: "按钮的类型,实心还是缕空normal/实心,ghost/缕空",
table: {
type: { summary: "string" },
defaultValue: {
summary: "normal"
}
},
options: ["normal", "ghost"],
control: {
type: "select"
}
},
shape: {
defaultValue: "default",
description: "按钮形状,default/柔和边角,square/直角边角,circle/圆弧边角",
table: {
type: { summary: "string" },
defaultValue: {
summary: "default"
}
},
options: ["default", "square", "circle"],
control: {
type: "select"
}
},
text: {
defaultValue: "this is a button",
description: "按钮内置的文案",
table: {
type: { summary: "string" },
defaultValue: {
summary: "this is a button"
}
},
control: {
type: "text"
}
},
disabled: {
defaultValue: false,
description: "是否禁用",
table: {
type: { summary: "boolean" },
defaultValue: {
summary: "false"
}
},
control: {
type: "boolean"
}
},
onClick: {
defaultValue: "",
description: "函数",
table: {
type: {
summary: "function"
},
defaultValue: {
summary: "() => {}"
}
},
control: {
type: null
}
},
isBgGrey: {
defaultValue: true,
description:
"当按钮禁用时,按钮背景是否置灰;此属性仅当disabled为true时生效",
table: {
type: {
summary: "boolean"
},
defaultValue: {
summary: "true"
}
},
control: {
type: "boolean"
}
},
isInline: {
defaultValue: false,
description: "是否行内元素(可以理解为是否非独占一行)",
table: {
type: {
summary: "boolean"
},
defaultValue: {
summary: "false"
}
},
control: {
type: "boolean"
}
},
size: {
defaultValue: "small",
description: "按钮的大小,large/大,small/小",
table: {
type: {
summary: "string"
},
defaultValue: {
summary: "small"
}
},
options: ["small", "large"],
control: {
type: "select"
}
},
style: {
defaultValue: {},
description: "自定义样式",
table: {
type: {
summary: "object"
},
defaultValue: {
summary: "例如marginLeft:50px添加到后面"
}
```
需要注意的点就是那些参数对应的是哪里,下面讲解一下就知道了
对应的效果如下图
argTypes就是右侧的这些参数
好到这里就结束了,看不懂的小伙伴也不要灰心喔,欢迎评论区评论交流。