HoRain云--React 组件
🎬 HoRain云小助手:个人主页
🔥 个人专栏: 《Linux 系列教程》《c语言教程》
⛺️生活的理想,就是为了理想的生活!
⛳️ 推荐
前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。
专栏介绍
专栏名称 | 专栏介绍 |
《C语言》 | 本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。 |
《网络协议》 | 本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制! |
《docker容器精解篇》 | 全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。 |
《linux系列》 | 本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。 |
《python 系列》 | 本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。 |
《试题库》 | 本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等) |
目录
⛳️ 推荐
专栏介绍
函数组件
src/Welcome.js 文件:
src/index.js 文件:
类组件
实例
实例
测试实例
React 实例
实例解析:
React 实例
复合组件
React 实例
Props(属性)
基础用法
Props 解构
Props 的类型
Children Props
Props 的不可变性
组件的组合与复用
组合模式
容器组件模式
高阶组件思想(通过组合实现)
组件命名规范
命名规则
文件命名
组件的导出与导入
默认导出
命名导出
混合导出
组件设计原则
1. 单一职责原则
2. 保持组件简洁
3. 合理使用 Props
4. 避免深层嵌套
React 组件是构建 React 应用的基本单元,可以把组件理解为可复用的、独立的 UI 单元,每个组件封装了自己的结构、样式、逻辑和状态。
React 组件是构建应用的基石,组件可以小到一个按钮,也可以大到整个页面。
组件可以分为:函数组件和类组件。
从技术角度讲,React 组件就是一个返回 React 元素(通常是 JSX)的 JavaScript 函数或类。
// 最简单的组件 function Hello() { return <h1>Hello, World!</h1>; }将复杂的 UI 拆分成组件树:
App ├── Header │ ├── Logo │ └── Navigation │ ├── NavItem │ └── NavItem ├── Main │ ├── Sidebar │ └── Content │ ├── Article │ └── Article └── Footer
函数组件
函数组件是定义组件的一种简洁方法。
函数组件是一个接受 props 并返回 React 元素的 JavaScript 函数。
基础语法:
// 方式 1:函数声明 function Welcome(props) { return <h1>Hello, {props.name}</h1>; } // 方式 2:箭头函数 const Welcome = (props) => { return <h1>Hello, {props.name}</h1>; }; // 方式 3:简化写法(单行返回) const Welcome = (props) => <h1>Hello, {props.name}</h1>;创建一个简单的函数组件:
src/Welcome.js 文件:
import React from 'react';
// 定义一个函数组件
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
export default Welcome;
在 src/index.js 中渲染该组件:
src/index.js 文件:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Welcome from './Welcome';
const root = ReactDOM.createRoot(document.getElementById("root"));
// 渲染 Welcome 组件,并传递 name 属性
root.render(<Welcome name="World" />);
这个例子展示了一个接受 name 属性并在页面上显示 "Hello, World!" 的简单组件。
类组件
类组件使用 ES6 类语法定义,通常用于需要管理状态或使用生命周期方法的情况。
基础语法:
import React, { Component } from 'react'; class Welcome extends Component { render() { return <h1>Hello, {this.props.name}</h1>; } }创建一个类组件:
实例
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Welcome;
在 src/index.js 中渲染该组件:
实例
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Welcome from './Welcome';
const root = ReactDOM.createRoot(document.getElementById("root"));
// 渲染 Welcome 组件,并传递 name 属性
root.render(<Welcome name="World" />);
测试实例
接下来我们封装一个输出 "Hello World!" 的组件,组件名为 HelloMessage:
React 实例
function HelloMessage(props) { return <h1>Hello World!</h1>; } const element = <HelloMessage />; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( element );
实例解析:
1、我们可以使用函数定义了一个组件:
function HelloMessage(props) { return <h1>Hello World!</h1>; }你也可以使用 ES6 class 来定义一个组件:
class Welcome extends React.Component { render() { return <h1>Hello World!</h1>; } }2、const element = <HelloMessage />为用户自定义的组件。
注意,原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头,比如 HelloMessage 不能写成 helloMessage。除此之外还需要注意组件类只能包含一个顶层标签,否则也会报错。
如果我们需要向组件传递参数,可以使用this.props对象,实例如下:
React 实例
function HelloMessage(props) { return <h1>Hello {props.name}!</h1>; } const element = <HelloMessage name="Runoob"/>; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( element );
以上实例中name属性通过 props.name 来获取。
注意,在添加属性时, class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。
复合组件
我们可以通过创建多个组件来合成一个组件,即把组件的不同功能点进行分离。
以下实例我们实现了输出网站名字和网址的组件:
React 实例
function Name(props) { return <h1>网站名称:{props.name}</h1>; } function Url(props) { return <h1>网站地址:{props.url}</h1>; } function Nickname(props) { return <h1>网站小名:{props.nickname}</h1>; } function App() { return ( <div> <Name name="菜鸟教程" /> <Url url="http://www.runoob.com" /> <Nickname nickname="Runoob" /> </div> ); } const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <App /> );
尝试一下 »
实例中 App 组件使用了 Name、Url 和 Nickname 组件来输出对应的信息。
Props(属性)
Props 是组件之间传递数据的方式,类似于函数的参数。
基础用法
// 父组件传递 props function App() { return ( <div> <Greeting name="Alice" age={25} /> <Greeting name="Bob" age={30} /> </div> ); } // 子组件接收 props function Greeting(props) { return ( <div> <h1>Hello, {props.name}!</h1> <p>Age: {props.age}</p> </div> ); }Props 解构
// 推荐:直接解构 function Greeting({ name, age }) { return ( <div> <h1>Hello, {name}!</h1> <p>Age: {age}</p> </div> ); } // 带默认值的解构 function Button({ text = "Submit", variant = "primary", disabled = false }) { return ( <button className={variant} disabled={disabled}> {text} </button> ); }Props 的类型
Props 可以是任何 JavaScript 值:
function Demo() { const user = { name: "Alice", age: 25 }; const numbers = [1, 2, 3, 4, 5]; const handleClick = () => alert("Clicked!"); return ( <MyComponent // 字符串 title="Hello" // 数字 count={42} // 布尔值 isActive={true} // 数组 items={numbers} // 对象 user={user} // 函数 onClick={handleClick} // JSX children={<p>This is content</p>} /> ); }Children Props
特殊的 props,用于传递组件的子内容:
// 方式 1:使用 props.children function Card(props) { return ( <div className="card"> <div className="card-body"> {props.children} </div> </div> ); } // 方式 2:解构 children function Card({ children, title }) { return ( <div className="card"> {title && <h2>{title}</h2>} <div className="card-body">{children}</div> </div> ); } // 使用 function App() { return ( <Card title="My Card"> <p>This is the card content</p> <button>Click me</button> </Card> ); }Props 的不可变性
重要原则:永远不要修改 props!
// 错误:修改 props function BadComponent(props) { props.name = "Changed"; // 绝对不要这样做! return <h1>{props.name}</h1>; } // 正确:将 props 视为只读 function GoodComponent({ name }) { const displayName = name.toUpperCase(); // 创建新值 return <h1>{displayName}</h1>; }组件的组合与复用
组合模式
// 基础组件 function Avatar({ src, alt }) { return <img src={src} alt={alt} className="avatar" />; } function UserInfo({ name, email }) { return ( <div> <h3>{name}</h3> <p>{email}</p> </div> ); } // 组合成复杂组件 function UserCard({ user }) { return ( <div className="user-card"> <Avatar src={user.avatar} alt={user.name} /> <UserInfo name={user.name} email={user.email} /> </div> ); }容器组件模式
// 容器组件:处理逻辑和状态 function Panel({ title, children, collapsible = false }) { const [isOpen, setIsOpen] = useState(true); return ( <div className="panel"> <div className="panel-header"> <h2>{title}</h2> {collapsible && ( <button onClick={() => setIsOpen(!isOpen)}> {isOpen ? "Collapse" : "Expand"} </button> )} </div> {isOpen && ( <div className="panel-content"> {children} </div> )} </div> ); } // 使用 function App() { return ( <Panel title="Settings" collapsible> <p>Your settings here...</p> </Panel> ); }高阶组件思想(通过组合实现)
// 通用的加载状态包装 function WithLoading({ isLoading, children }) { if (isLoading) { return <div>Loading...</div>; } return children; } // 使用 function UserList({ users, isLoading }) { return ( <WithLoading isLoading={isLoading}> <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> </WithLoading> ); }组件命名规范
命名规则
// 正确:大写字母开头(PascalCase) function UserProfile() { } function BlogPost() { } function NavBar() { } // 错误:小写字母开头 function userProfile() { } // React 会将其视为 HTML 标签文件命名
// 推荐的文件结构 src/ ├── components/ │ ├── Button.jsx // 或 Button.js │ ├── UserCard.jsx │ ├── Navigation/ │ │ ├── Navigation.jsx │ │ ├── NavItem.jsx │ │ └── index.js // 导出 Navigation
组件的导出与导入
默认导出
// Button.jsx export default function Button({ text }) { return <button>{text}</button>; } // App.jsx import Button from './Button';命名导出
// components.jsx export function Button({ text }) { return <button>{text}</button>; } export function Input({ value, onChange }) { return <input value={value} onChange={onChange} />; } // App.jsx import { Button, Input } from './components';混合导出
// Card.jsx export default function Card({ children }) { return <div className="card">{children}</div>; } export function CardHeader({ title }) { return <div className="card-header">{title}</div>; } export function CardBody({ children }) { return <div className="card-body">{children}</div>; } // App.jsx import Card, { CardHeader, CardBody } from './Card';组件设计原则
1. 单一职责原则
每个组件应该只做一件事。
// 不好:组件做太多事情 function UserDashboard() { // 获取用户数据 // 处理表单 // 显示图表 // 处理导航 // ... } // 好:拆分成多个组件 function UserDashboard() { return ( <div> <UserProfile /> <UserStats /> <UserActivity /> </div> ); }2. 保持组件简洁
组件代码不应该超过 200-300 行。
// 好:提取子组件 function ProductCard({ product }) { return ( <div className="product-card"> <ProductImage src={product.image} /> <ProductInfo name={product.name} price={product.price} /> <ProductActions productId={product.id} /> </div> ); }3. 合理使用 Props
不要传递过多的 props。
// 不好:props 过多 function User({ name, age, email, address, phone, company, role, ... }) { } // 好:使用对象 function User({ user }) { const { name, age, email } = user; // ... }4. 避免深层嵌套
过深的组件嵌套会导致 props drilling 问题。
// 问题:props 需要层层传递 <App> <Layout user={user}> <Sidebar user={user}> <Menu user={user}> <MenuItem user={user} /> </Menu> </Sidebar> </Layout> </App> // 解决:使用 Context 或状态管理
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
