前言
在上一章 React 简单教程-3-样式 中我们建立了一个子组件,并稍微美化了一下。在另一篇文章 React 简单教程-3.1-样式之使用 tailwindcss 章我们使用了 tailwind 来写样式,以后我代码里的样式都会使用 tailwind 来写。
这一章,我将给我们的子组件加一个按钮,以实现交互的功能。
什么功能?
我们现在的子组件如下图:
现在它没有交互功能,我想给他的灰色按钮加一个点击事件,点击后将内容收起,如下:
实现
首先,我们的灰色按钮,现在只是一个 span 元素,需要先将它换成 button 元素,样式不变,我们只需要直接将标签从 span 换成 button 就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
export function Displayer(props: { name: string, content: string }) { const name = props.name; const content = props.content; return ( <div className="bg-gray-800 text-white p-2 m-2 rounded-lg"> <div className="nav"> <span className="btn-red"></span> <span className="btn-yellow"></span> {/* 灰色按钮 */} <button className="btn-gray"></button> </div> <div className="body"> <div>{name}</div> <div>{content}</div> </div> </div> ); } |
之后添加点击事件。就跟我们在 html 元素上添加一样,在按钮的 onclick 里绑定事件,React 也一样,但是写法需要是小驼峰写法:onClick,React 的组件所有属性都是小驼峰下发。我们在组件里定义一个方法用来处理这个按钮的事件,然后将方法赋给 onClick 属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
export function Displayer(props: { name: string, content: string }) { // 忽略 // 定义的处理方法 function handleClick() {} return ( <div className="bg-gray-800 text-white p-2 m-2 rounded-lg"> {/* 忽略 */} {/* 灰色按钮 */} <button className="btn-gray" onClick={handleClick}></button> {/* 忽略 */} </div> ); } |
我们绑定方法的时候,方法名要写在花括号里,根据规范,处理事件的方法一般以 handle 开头。现在我们的方法 handleClick 里没有任何实现。
接下来,要隐藏我们的内容元素,可以直接使用 hidden 属性来隐藏:
1 |
<div className="body" hidden></div> |
但是这是静态的操作,我们要在点击按钮后动态隐藏。我们会想到定义一个变量 isHidden,将变量赋给要隐藏的元素:
1 |
<div className="body" hidden="{isHidden}"></div> |
通过按钮事件,将值变为 true,当值为 true 时,元素就隐藏了。但是如果你试一遍的话,就会发现是不起效的。因为你只是改变了变量,没有重绘界面,所以界面是不会变化的。
在 React 里需要怎么做呢?
使用 useState hook
什么是 hook?在本文中,我不打算详细介绍什么是 hook(下一章里我会介绍),但是我想先让你感受下 hook。在 react 中,你会经常看到以 use 开头的方法,你可以认为这些方法就是 hook,是 React 提供的用于实现一些特性的功能。这里我们将使用这个 hook 来解决上面的问题。
hook useState 是干什么的?跟随下面一边写一边感受一下。
导入 useState 并使用:
1 2 3 4 5 6 7 |
// 导入 hook import { useState } from "react"; export function Displayer(props: { name: string, content: string }) { // 使用 hook const [hidden, setHidden] = useState(false); } |
看示例,hook 就是一个方法,也跟使用方法一样使用。在示例中,useState(false) 返回了一个数组,数组中的第一个参数是一个变量,第二个参数是修改这个变量的方法,使用 useState 可以传入这个变量的默认值,在示例中,我传入了 false,根据类型推断,数组中的第一个参数被推断出是 boolean 类型。
从这里,你应该能够看出,hook useState 的作用是创建变量。和一般变量的不同的地方在于,它提供了修改这个变量的方法 setHidden,这个修改的方法,特点在于,它会重绘这个组件!
也就是说,当我们调用 setHidden,传入新的值,修改了变量后,它会让这个组件的界面更新一遍,这样,组件的界面就可以发生变化了!
在我们的子组件中感受一下,使用 useState 创建的变量来代替我们的 isHidden 变量,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
export function Displayer(props: { name: string, content: string }) { // 忽略 const [hidden, setHidden] = useState(false); function handleClick() { setHidden(true); } return ( <div className="bg-gray-800 text-white p-2 m-2 rounded-lg"> <div className="nav"> {/* 忽略 */} <button className="btn-gray" onClick={handleClick}></button> </div> <div className="body" hidden={hidden}> {/* 忽略 */} </div> </div> ); } |
在上面的代码上,按钮 button 的 onClick 绑定了处理函数,函数里调用了 setHidden(true);,将 hidden 的值设为 true,并触发了重绘,重绘时,因为 hidden 的值为 true,内容元素的 hidden 被触发,内容元素隐藏。
就这样,实现了我们点击隐藏的效果。亲手试一试,感受一下 hook。
扩展习题
你能不能扩展这个功能,让按钮再点击一下,就展开内容元素?
总结
- 本文章我们学会了按钮元素点击事件的用法。其他事件的用法也大同小异,比如 onChang。
- 学会了第一个 hook:useState,并知道这个 hook 起到了什么作用。