一个按钮可能是你在React组件中使用的第一个交互式元素。因此,这是一个简短的React教程,通过实例向初学者介绍在React中创建一个按钮,如何使用它,以及如何将它提取为一个可重用的组件。首先,按钮只是一个HTML按钮元素,可以在React的JSX中呈现:
import * as React from 'react';
const App = () => {
return (
<div>
<button type="button">Click Me</button>
</div>
);
};
export default App;
通过使用React中的事件处理程序,我们可以对按钮的点击事件做出反应:
import * as React from 'react';
const App = () => {
const handleClick = () => {
// implementation details
};
return (
<div>
<button type="button" onClick={handleClick}>
Click Me
</button>
</div>
);
};
export default App;
这样,一个按钮就可以用来在点击它时触发各种效果。例如,通过使用React的useState Hook,它可以改变一个有状态的值:
import * as React from 'react';
const App = () => {
const [count, setCount] = React.useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<button type="button" onClick={handleClick}>
Click Me
</button>
{count}
</div>
);
};
export default App;
另一个例子是切换一个条件渲染:
import * as React from 'react';
const App = () => {
const [isOpen, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!isOpen);
};
return (
<div>
<button type="button" onClick={handleClick}>
Click Me
</button>
{isOpen && <div>Content</div>}
</div>
);
};
export default App;
总之,不管这个按钮在它的onClick处理程序上毕竟执行什么,你可能想为它创建一个可重用的组件。因此,我们将提取它作为一个新的函数组件,并将必要的道具传递给它:
import * as React from 'react';
const App = () => {
const [isOpen, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!isOpen);
};
return (
<div>
<Button onClick={handleClick}>Toggle</Button>
{isOpen && <div>Content</div>}
</div>
);
};
const Button = ({ onClick, children }) => {
return (
<button type="button" onClick={onClick}>
{children}
</button>
);
};
export default App;
我们的Button组件现在是一个可重复使用的组件。例如,如果你在React中给你的输入字段一些CSS样式,那么在你的React项目中使用的每个Button组件都会使用同样的样式。
如果你现在想创建一个按钮组,你可以使用多个Button组件并排使用:
import * as React from 'react';
const App = () => {
const [isOpen, setOpen] = React.useState(false);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button onClick={handleOpen}>Open</Button>
<Button onClick={handleClose}>Close</Button>
{isOpen && <div>Content</div>}
</div>
);
};
const Button = ({ onClick, children }) => {
return (
<button type="button" onClick={onClick}>
{children}
</button>
);
};
export default App;
从这里,你可以用许多功能来扩展你的Button组件。例如,类型不一定是按钮,但可以是submit ,用于处理React中的表单。因此,我们可以让外部的开发者为Button传递一个可选的type 道具,如果没有传递的话,内部默认为button 。
const Button = ({ type = 'button', onClick, children }) => {
return (
<button type={type} onClick={onClick}>
{children}
</button>
);
};
或者你可以在Button组件不应该被点击的时候给它传递一个disabled 的道具。因为如果不提供的话,它的默认值是undefined ,所以按钮元素不会被禁用:
const Button = ({ type = 'button', disabled, onClick, children }) => {
return (
<button type={type} disabled={disabled} onClick={onClick}>
{children}
</button>
);
};
然而,向Button组件传递所有这些额外的信息是很麻烦的。在一个完美的世界里,所有这些信息应该被Button组件接受,就像我们使用一个单纯的按钮元素一样。我们可以通过使用JavaScript的rest destructuring来实现React的props:
const Button = ({ type = 'button', onClick, children, ...rest }) => {
return (
<button type={type} onClick={onClick} {...rest}>
{children}
</button>
);
};
现在,无论我们把一个disabled 布尔值还是一个style 对象传给Button组件,在内部它都会把它传给按钮元素。这样一来,Button元素的行为就和按钮元素相似。所有更明确的东西,比如onClick处理程序或type 道具的默认值,都需要明确写在Button组件的函数签名中。