-
React 组件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 是组件之间传递数据的方式,类似于函数的参数。基础用法// 父组件传递 propsfunction App() { return ( <div> <Greeting name="Alice" age={25} /> <Greeting name="Bob" age={30} /> </div> );}// 子组件接收 propsfunction 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.childrenfunction Card(props) { return ( <div className="card"> <div className="card-body"> {props.children} </div> </div> );}// 方式 2:解构 childrenfunction 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!// 错误:修改 propsfunction 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.jsxexport default function Button({ text }) { return <button>{text}</button>;}// App.jsximport Button from './Button';命名导出// components.jsxexport function Button({ text }) { return <button>{text}</button>;}export function Input({ value, onChange }) { return <input value={value} onChange={onChange} />;}// App.jsximport { Button, Input } from './components';混合导出// Card.jsxexport 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.jsximport 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 或状态管理
-
1.1 问题说明用户想将中文字符串转拼音字符,没有很好的工具类1.2 原因分析没有使用好用的工具类和转化方法1.3 解决思路1)导入拼音工具类2)使用工具类转化方法3)输出转化结果1.4 解决方案1)导入i18n拼音库import { i18n } from '@kit.LocalizationKit';2)常用的拼音编码转化成带音标的:let transliterator1 = i18n.Transliterator.getInstance('Any-Latn');this.lantinMsg = transliterator1.transform(this.message); 转化成不带音标let transliterator2 = i18n.Transliterator.getInstance('Latin-ASCII');this.asciiMsg = transliterator2.transform(this.lantinMsg); 3)案例截图
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签