创建可重用的组件的第一步是识别它。首先去寻找原子组件,像button、input等等。然后去使用原子组件来制作templates,使用templates来制作pages
下面的代码片段是一简单的button组件。使用HTMLAttributes
来获取button元素的默认属性类型
/* Button.module.css */.btn {padding: 0.5rem 1rem;}
// Button.tsximport { HTMLAttributes } from "react";import styles from "./Button.module.css";type TProps = HTMLAttributes<HTMLButtonElement>;export const Button = ({ children, ...props }: TProps) => {return (<button className={styles.btn} {...props}>{children}</button>)}
当开发一个React,需要定义它的states。 就像Button组件可以enabled或者disabled,可以是primary或者是secondary。同一时间内,一个按钮可以有多个状态,就像Button可以是主状态并处于禁用状态一样。我们会使用自定义属性来改变组件的状态。
下面的代码片段展示了带有variety和isDisabled可选属性的Button组件。我们将基于这些属性来改变按钮的状态。
/* Button.module.css */.btn {padding: 0.5rem 1rem;}.secondaryBtn {background-color: #5f5757;color: rgb(21, 5, 5);}
import { HTMLAttributes } from "react";import styles from "./Button.module.css";type TProps = HTMLAttributes<HTMLButtonElement> & {variety?: "primary" | "secondary";isDisabled?: boolean;};export const Button = ({children,variety = "primary",isDisabled = false,...props}: TProps) => {return (<buttonclassName={`${styles.btn} ${variety === "secondary" && styles.secondaryBtn}`}disabled={isDisabled}{...props}>{children}</button>)}
我们不知道组件会用在哪里。所以你可以给一个最小宽度或者最小高度而不是设定固定的宽度或者高度。你可以给宽度设置成100%,或者传入className或者style属性,这样我们通过传入这些属性来改变style
下面的代码片段中通过传入className和style来改变Button组件的样式
// Button.tsximport { HTMLAttributes } from "react";import styles from "./Button.module.css";type TProps = HTMLAttributes<HTMLButtonElement> & {variety?: "primary" | "secondary";isDisabled?: boolean;};export const Button = ({children,variety = "primary",isDisabled = false,className,style,...props}: TProps) => {return (<buttonstyle={style}className={`${styles.btn} ${variety === "secondary" && styles.secondaryBtn} ${className}`}disabled={isDisabled}{...props}>{children}</button>)}
如果组件中有一些逻辑需要执行,比如执行Button组件的单击操作。不要在组件内部编写处理函数,而是将其作为props传递。尝试将所有依赖项作为props传递。保持组件的无状态是一个很好的实践。
// Button.tsximport { HTMLAttributes } from "react";import styles from "./Button.module.css";type TProps = HTMLAttributes<HTMLButtonElement> & {variety?: "primary" | "secondary";isDisabled?: boolean;};export const Button = ({children,variety = "primary",isDisabled = false,className,style,...props}: TProps) => {return (<buttonstyle={style}className={`${styles.btn} ${variety === "secondary" && styles.secondaryBtn} ${className}`}disabled={isDisabled}{...props}>{children}</button>);};
// index.tsximport type { NextPage } from "next";import styles from "../styles/Home.module.css";import { Button } from "../components/Button";const Home: NextPage = () => {const handleClick = () => {setTimeout(() => {alert("Clicked!");}, 1000);};return (<div className={styles.container}><Button variety="secondary" onClick={handleClick}>Click</Button></div>);};export default Home;