React Props 教程 - 制作一个按钮
2020年3月 · 预计阅读时间: 5 分钟
你在写 HTML 页面的时候肯定知道,html 标签的属性都是固定的,比如 a
标签的 href
, input
里边的 type
属性。这些属性都是内置的,不方便扩展和复用。而用 React 创建组件的话,可以给它定义一些更符合语义和逻辑的属性,比如颜色、尺寸等。这些属性在 React 里边叫做 props,你可以自己定义这些属性将会影响到组件的哪些部分。这样的一个组件,通过给它一个合适的名字,比如 Button,那么所有按钮的展现都可以用它来实现,只需要改变它的属性就可以展示为不同的样式。那今天我就教你定义一个这样的按钮组件,它有默认的背景色、文字颜色、还有实心和线框样式,后边通过属性,props,来控制它是蓝色、红色还是黑色,然后利用另一个属性来控制它是实心的背景还是线框的。好,那咱们开始吧。
你将学到的
上一张效果图:
创建 React 工程
-
使用 create-react-app 创建一个工程:
yarn create react-app react-button-props
等同于
npx create-react-app react-button-props
-
添加
classnames
依赖(稍后解释它的作用)yarn add classnames
创建 Button 组件
-
在
src
下边新建一个Button
文件夹。组件应该有自己独立的文件夹,所有跟这个组件有关的文件,比如 css、hooks 等都放到一起,这样在查看一个组件源码时,相应的文件都会在一块,方便查找。另外也方便和其他人共享这个组件,它是一个独立的整体。 -
在
Button
文件夹创建index.js
文件,里边放用来定义按钮组件的代码。 -
在
Button
文件夹下创建style.modules.css
文件,在这里咱们先用普通的 css 来定义按钮的样式,后续的教程里我再给你介绍styled-components
。它是一个 css-in-js 的解决方案CSS modules 的作用这个带 modules 的 css 文件使用了
css modules
库,它是 create-react-app 工具里自带的,用来避免全局 class 名字冲突,在普通 css 下,如果不同的样式文件都同时使用了.button
这样的 class 名,那么后面的就会把前面的覆盖。使用了css modules
之后,它会自动生成随机的 class 名字。这样这个组件里边定义的 class 就不会被其他组件定义的同名的 class 给覆盖。当然你也可以不用它,有些全局的 css 可以直接定义在普通的 css 文件里。 -
编写
button
组件的代码:import React from "react";
function Button(props) {
return <button>{props.children}</button>;
}
export default Button;react 中的组件默认都会被传递一个
props
属性,里边会默认包含一个 children 属性,也就是说在使用<Button />
组件时,两个标签中间所有的代码都会当作 children 传递进来。上边的代码,也可以使用 rest 操作符简化:function Button({ children }) {
return <button>{children}</button>;
}比如:
function App() {
// 作为演示,我在 App 组件里又定义了一个 Button 组件
function Button({ children }) {
return <button>{children}</button>;
}
return <Button>按钮</Button>;
} -
删除 App 的 return 中的所有的代码,导入 Button 组件,然后把它写在 return 里边:
function App() {
return <Button>默认按钮</Button>;
}
编写 Button 默认样式
-
打开 Button 组件下的
style.modules.css
文件,写上下边的 css 代码:.button {
padding: 12px 48px;
border-radius: 24px;
background-color: #0076ff;
box-shadow: 0px 4px 10px rgba(135, 167, 171, 0.5);
font-size: 14px;
color: white;
font-weight: 500;
text-shadow: 0px 0.5px 1px rgba(0, 0, 0, 0.15);
outline: none;
cursor: pointer;
}这里把按钮设置了背景、圆角边框、字体、指针样式和阴影。
-
打开 Button 组件的 index.js 文件,导入 css 文件并赋值给一个变量,这里叫
styles
:import styles from "./styles.module.css";
-
给 Button 组件加上 className 属性,这里可以用
styles.button
来访问 css 文件中的.button
的样式:<button className={styles.button}>{children}</button>
可以在页面上看到,这个默认按钮的样式已经加载好了。
用 Props 给 Button 不同的样式
在给 Button 写完默认样式之后,咱们再来定义它几个变体,比如红色、黑色。你可以在 Button 里多添加一个 color 属性,代表其他组件使用它时,可以传递一个 color 属性,Button 会根据它的值显示不同的颜色,这里我假设它有三种,一种是默认的蓝,就是不传 color 的时候的颜色,一种是红色,color 的值为 red 的时候显示,一种是黑色,在 color 为 black 的时候显示。首先咱们先把这两种颜色的 css 样式定义好:
.red {
background-color: #ff4059;
}
.black {
background-color: #2e3434;
}
classnames 组合样式
在定义完这两个额外的样式之后,需要把它和.button
定义的样式组合起来。这里可以手动去拼,也可以用之前刚开始安装的 classnames 依赖库。它可以根据条件来组合 className,只有满足一定条件的 class 才会被组合进来,在咱们这里,可以这样使用:
<button
className={classNames(styles.button, {
[styles.red]: color === "red",
[styles.black]: color === "black"
})}
>
{children}
</button>
它接收多个参数,第一个直接传递了 styles.button 这个 class,说明它无论其它属性怎么变化,它都是要有的,最后传递了一个对象,对象的 key 是 styles 中的 class 的名字,value 是 boolean 类型的,需要一个条件,返回 true 就把这个 class 加到组合中,false 就不加。那这里,如果 color 的值是 red,那么 button 中就会有 .red
定义的样式。
再在 App.js 中添加两个按钮 ,一个 color 设置为 red,一个 color 设置为 black:
<main>
<div>
<Button>默认按钮</Button>
<Button color="red">红色按钮</Button>
<Button color="black">黑色按钮</Button>
</div>
</main>
需要注意的是,react 要求在返回的 JSX 中只能有一个顶级的标签,不能有并列的多个,比如不能同时写三个 button,需要把它们包装在一个大的标签下,这里我用了一个 main,作为内容容器,里边有一个 div 是 button 的容器。
线框样式
如果再加一组线框样式的按钮呢?很简单,我再加一个type
属性,默认是primary
的,主要按钮,线框按钮的 type 叫它secondary
次要按钮,然后 classnames 添加一个新的 class,在 type 为 secondary
的时候追加到组合中:
function Button({ children, type = "primary", color = "blue" }) {
return (
<button
className={classNames(styles.button, {
[styles.red]: color === "red",
[styles.black]: color === "black",
[styles.secondary]: type === "secondary"
})}
>
{children}
</button>
);
}
接下来定义 secondary
样式:
.secondary {
background: none;
border: 2px solid #0076ff;
color: #0076ff;
}
.secondary.red {
border-color: #ff4059;
color: #ff4059;
}
.secondary.black {
border-color: #2e3434;
color: #2e3434;
}
在这里我把默认蓝色、红色、黑色按钮的边框和文字都设置了不同的颜色。
显示所有按钮样式
在 App.js 中咱们显示所有不同属性的按钮,然后给按钮容器加上一个 className,用来对按钮进行排版,这里我直接用了普通的 css 样式,也就是创建工程时给生成好的 App.css,直接把它导入进来:
App.js
// 省略函数定义
<main>
<div className="btn__container">
<Button>默认按钮</Button>
<Button color="red">红色按钮</Button>
<Button color="black">黑色按钮</Button>
<Button type="secondary">线框按钮</Button>
<Button type="secondary" color="red">
线框按钮
</Button>
<Button type="secondary" color="black">
线框按钮
</Button>
</div>
</main>
App.css
main {
width: 100vw;
height: 100vh;
background-color: #f2f2f2;
display: flex;
align-items: center;
justify-content: center;
}
.btn__container {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 24px;
row-gap: 24px;
align-content: center;
justify-items: center;
}
好了,这个使用 React Props 来展示不同样式的按钮到这里就结束了,里边几个概念:
- React 组件默认会传递 Props 参数
- 使用 props 可以传递任何自定义的属性
- 组件相关的文件都放到一个文件夹里
css modules
- 用来生成随机局部 class 名字classnames
- 用来组合多个 class
你学会了吗?如果有问题,欢迎通过下方链接参与讨论。