React - 组件
接 使用 Vite 创建一个 React 项目 这篇文章,以下是目前搭建好的页面效果

从图中可以看到,整体的一个布局元素:
- 顶部导航栏
- 左侧
- logo
- navList
- 右侧
- 暗黑主题切换开关
- login 按钮
- 左侧
- 内容部分(路由嵌套,跳转时局部显示内容)
目录
一个项目中,我们肯定会有需要用到组件封装的地方,然后会用到组件通信,获取数据等等,所以这里我们简单的看下 React 中组件的使用和组件通信。
- 类组件
- 函数组件
- 组件通信
以下的介绍,无论是 类组件 和 函数组件,我都会使用同一个例子,这个例子也在项目中实际使用,具体的代码可以在项目中查找对应组件看到。
类组件
第 1 步 - 创建一个 NavBar 组件
使用类组件,需要继承
React.Component,以及写一个render函数,在这个函数中去return你需要返回的页面结构。
在 src/components/NavBar 下新建一个 NavBar.jsx 文件,代码如下:
class NavBar extends React.Component {
render() {
return (
<div className=""></div>
)
}
}
export default NavBar需要注意的是,在 React 中,我们一般使用 className 而不是 class,这是因为 class 在 JavaScript 中是一个保留字,所以不能使用。
第 2 步 - 在 Layout 页面中使用 NavBar 组件
在 src/containers/layout 下新建一个 layout.jsx 文件,代码如下:
import Navbar from "@/components/NavBar/NavBar";
class Layout extends React.Component {
render() {
return (
<div className="layout">
<NavBar />
</div>
)
}
}
export default Layout函数组件
在 函数组件 中,我们只需使用 function 关键字定义一个函数,然后在这个函数中 return 你需要返回的页面结构即可。
export default function NavBar() {
return (
<div className=""></div>
)
}组件通信
类组件通信
- 父传子
在 Layout 页面中,引用 NavBar 组件,并向它传递 NavList 数组。
父组件 - Layout.jsx
class Layout extends React.Component {
render() {
const navList = [
{
title: 'Home',
path: '/home'
},
{
title: 'Record',
path: '/record'
},
];
return (
<div className="layout">
<NavBar navList={navList} />
</div>
)
}
}
export default Layout接收 父组件 传来的参数,我们使用 this.props.navList 来接收。
由于 navList 是一个数组, 我们需要使用 map 方法把它遍历出来。
props 是父组件传给子组件的一个对象,里面包含了要传的所有值
子组件 - NavBar.jsx
class NavBar extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="home-nav-list">
{
this.props.navList.map((item, index) => {
return (
<NavLink
className={({ isActive }) => isActive ? "home-nav-list-item active" : "home-nav-list-item"}
to={item.path}
key={index}
onClick={}
>
{item.title}
</NavLink>
)
})
}
</div>
)
}
}
export default NavBar- 子传父
在 NavBar 组件中,引用了 ThemeToogle 组件,来控制 主题切换。当子组件点击时,会向父组件传递当前是否为暗黑主题,由这个参数来作为 NavBar 组件中,左侧 logo 不同主题下的内容显示。
首先,我们在
constructor中,定义一个this.state对象,来存储当前状态值isDarkTheme。写一个方法
getThemeState用于接收子组件传递来的值,并且通过this.setState,来修改state中的isDarkTheme值。在
NavBar组件中,给ThemeToggle组件,传递定义好的getThemeState方法在
return中,使用时,通过this.state.xxx来使用变量
父组件 - NavBar.jsx
class NavBar extends React.Component {
constructor(props) {
super(props);
this.state = {
isDarkTheme: false // 是否为暗黑主题
};
}
// 更改主题状态值
getThemeState = (data) => {
this.setState({ isDarkTheme: data });
}
render() {
return (
<div className="home-nav">
<div className="home-nav-lt flex-al">
{/* logo */}
<Link to="/">
<img src={this.state.isDarkTheme ? logoDark : logo} className="logo"></img>
</Link>
{/* navList */}
<div className="home-nav-list flex-al"></div>
</div>
<div className="home-nav-rt flex-al">
{/* ThemeToggle */}
<ThemeToggle getThemeState={this.getThemeState} />
</div>
</div>
)
}
}
export default NavBar在子组件中,通过获取输入框的值,向父组件传递当前 e.target.checked 所获取到的值。
子组件通过 this.props.getThemeState 来调用父组件中的 getThemeState 方法,并把值传递给父组件。
子组件 - ThemeToogle.jsx
class ThemeToogle extends React.Component {
// 获取输入框的值
handleGetInputValue = (e) => {
// 从input点击事件获取的是值
let isDark = e.target.checked;
// 把值传递给 NavBar 父组件
this.props.getThemeState(isDark);
// 切换主题
if (isDark) {
...
} else {
...
}
}
render() {
return (
<>
<input type="checkbox" id="darkmode-toggle"
onChange={this.handleGetInputValue}
/>
<label htmlFor="darkmode-toggle">
<svg className="sun"></svg>
<svg className="moon"></svg>
</label>
</>
)
}
}
export default NavBar函数组件通信
与 类组件 的区别,大概就是:
通过
useState来初始化状态值且通过
useState中,定义好的setXXX,来更改状态值在
return中使用时,直接使用变量,不用再另外加this
- 父传子
layout 父页面,这里跟上面一样,我就不写了,主要写一下,子组件 NavBar 接收参数
因为是 函数组件 ,所以我们直接在 函数组件 中添加 props 参数。 使用时,直接使用 props.xxx 即可,不用再加 this。
子组件 - NavBar.jsx
export default function NavBar(props) {
return (
<div className="home-nav-list">
{
props.navList.map((item, index) => {
return (
<NavLink
className={({ isActive }) => isActive ? "home-nav-list-item active" : "home-nav-list-item"}
to={item.path}
key={index}
onClick={}
>
{item.title}
</NavLink>
)
})
}
</div>
)
}- 子传父
在
NavBar父组件中,通过useState来初始化状态值,这里我们初始化为false。以及定义好setXXX方法,来更改状态值。定一个
getThemeState方法,给ThemeToggle组件传递 ,这个方法会接收子组件传递过来的值,然后调用setIsDarkTheme方法,来更新状态值。定义变量 和 方法 时,别忘了加上
const在
return中使用的时候,不用加上this
父组件 - NavBar.jsx
export default function NavBar(props) {
// 主题切换 状态初始化
const [isDarkTheme, setIsDarkTheme] = useState(false);
// 更改主题状态值
const getThemeState = (data) => {
setIsDarkTheme(data);
}
return (
<div className="home-nav">
<div className="home-nav-lt flex-al">
{/* logo */}
<Link to="/">
<img src={isDarkTheme ? logoDark : logo} className="logo"></img>
</Link>
{/* navList */}
<div className="home-nav-list flex-al"></div>
</div>
<div className="home-nav-rt flex-al">
{/* ThemeToggle */}
<ThemeToggle getThemeState={getThemeState} />
</div>
</div>
)
}子组件中,别忘了添加参数 props,以及给方法加上 const
子组件 - ThemeToogle.jsx
export default function ThemeToogle(props) {
// 获取输入框的值
const handleGetInputValue = (e) => {
// 从input点击事件获取的是值
let isDark = e.target.checked;
// 把值传递给 NavBar 父组件
props.getThemeState(isDark);
// 切换主题
if (isDark) {
...
} else {
...
}
}
render() {
return (
<>
<input type="checkbox" id="darkmode-toggle"
onChange={handleGetInputValue}
/>
<label htmlFor="darkmode-toggle">
<svg className="sun"></svg>
<svg className="moon"></svg>
</label>
</>
)
}
}插槽 - slot
在 React 中,我们怎么实现 Vue 里的,<slot></slot> ?
默认插槽
- 类组件
父组件 - NavBar.jsx
class NavBar extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<>
<Container className="container">
<div className="home-nav-list"></div>
</Container>
</>
)
}
}
export default NavBar子组件 - Containerr.jsx
class Container extends React.Component {
render() {
// this.props.children; 通过props.children 可以打印出来看出组件的信息
return (
<div className="container">
{this.props.children}
</div>
)
}
}
export default Container- 函数组件
与 类组件 类似,就是在 子组件 中,把 this 去除即可