学习React官方文档(描述UI)
个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js
🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧
文章目录
- 创建 React 项目
- 我的第一个组件
- 使用 JSX 书写标签语言
- 在 JSX 中通过大括号使用 JavaScript
- 将 Props 传递给组件
- 条件渲染
- 渲染列表
- 保持组件纯粹
- 将 UI 视为树
- 总结
创建 React 项目
GitHub提交记录
我们可以使用 vite 构建工具创建 react 项目。
npm create vite@latest my-app -- --template reactcd my-appnpm installnpm run dev
访问:http://localhost:5173/ 网址,即可得到如下页面。
我的第一个组件
GitHub提交记录
几个注意事项:
- React 组件是常规的 JavaScript 函数,但组件的名称必须以大写字母开头,否则它们将无法运行!
- 没有括号包裹的话,任何在 return 下一行的代码都将被忽略!
- 组件可以渲染其他组件,但是不要嵌套他们的定义,不然代码会非常慢,并且会导致 bug 产生。应该在顶层定义每个组件,当子组件需要使用父组件的数据时,需要通过 props 的形式进行传递,而不是嵌套定义。
添加 src/Profile.jsx
文件。
export default function Profile() {return (<><p>伟大的科学家</p><imgsrc="https://i.imgur.com/MK3eW3Am.jpg"alt="Katherine Johnson"/></>)
}
把 Profile.jsx 放入 App.jsx。
import './App.css'
import Profile from './Profile'function App() {return (<><Profile /></>)
}export default App
使用 JSX 书写标签语言
GitHub提交记录
JSX 是 JavaScript 语法扩展,可以让你在 JavaScript 文件中书写类似 HTML 的标签。
规则:
- 只能返回一个根对象
- 标签必须闭合
- 使用驼峰式命名法给
所有大部分属性命名
创建 src/TodoList.jsx
文件,若不想在标签中增加一个额外的 <div>
,可以用 <>
和 </>
元素来代替。这个空标签被称作 Fragment。React Fragment 允许你将子元素分组,而不会在 HTML 结构中添加额外节点。
为什么多个 JSX 标签需要被一个父元素包裹?
答:JSX 虽然看起来很像 HTML,但在底层其实被转化为了 JavaScript 对象,你不能在一个函数中返回多个对象,除非用一个数组把他们包装起来。这就是为什么多个 JSX 标签必须要用一个父元素或者 Fragment 来包裹。
为什么要使用驼峰命名?
答:JSX 最终会被转化为 JavaScript,而 JSX 中的属性也会变成 JavaScript 对象中的键值对。在你自己的组件中,经常会遇到需要用变量的方式读取这些属性的时候。但 JavaScript 对变量的命名有限制。例如,变量名称不能包含 - 符号或者像 class 这样的保留字。
export default function TodoList() {return (<><h1>海蒂·拉玛的待办事项</h1><img src="https://i.imgur.com/yXOvdOSs.jpg" alt="Hedy Lamarr" className="photo"style={{ width: '200px', borderRadius: '10px' }}/><ul><li>发明一种新式交通信号灯</li><li>排练一个电影场景</li><li>改进频谱技术</li></ul></>);
}
在 JSX 中通过大括号使用 JavaScript
GitHub提交记录
JSX 允许你在 JavaScript 中编写类似 HTML 的标签,从而使渲染的逻辑和内容可以写在一起。
在 JSX 中使用 JavaScript 很简单,只需要使用 {}
包裹着即可。有时我们会在 JSX 中看到 {{
和 }}
,其实它只不过是 包在大括号里的一个对象 罢了。
下面我们尝试在 TodoList.jsx
中通过 {}
使用 JavaScript。
export default function TodoList() {const person = {name: "海蒂·拉玛",avatar: "https://i.imgur.com/yXOvdOSs.jpg",theme: {backgroundColor: "orange",color: "white",borderRadius: "10px",padding: "10px",},todolist: ["发明一种新式交通信号灯", "排练一个电影场景", "改进频谱技术"],};return (<div style={person.theme}><h1>{person.name}的待办事项</h1><imgsrc={person.avatar}alt="Hedy Lamarr"className="photo"style={{ width: "200px", borderRadius: "10px" }}/><ul><li>{person.todolist[0]}</li><li>{person.todolist[1]}</li><li>{person.todolist[2]}</li></ul></div>);
}
将 Props 传递给组件
GitHub提交记录
React 组件使用 props 来互相通信。每个父组件都可以提供 props 给它的子组件,从而将一些信息传递给它。
将父组件的信息传递给子组件非常的简单,只需要在父组件中定义需要传递的内容,然后在子组件中 通过参数接受 即可。
我们修改 src/Profile.jsx
文件。
import { getImageUrl } from "./utils";function Avatar({ person, size }) {const defaultStyle = {borderRadius: "50%",padding: "5px",};return (<><imgstyle={defaultStyle}className="avatar"src={getImageUrl(person)}alt={person.name}width={size}height={size}/></>);
}export default function Profile() {return (<div><Avatarsize={100}person={{name: "Katsuko Saruhashi",imageId: "YfeOqp2",}}/><Avatarsize={80}person={{name: "Aklilu Lemma",imageId: "OKS67lh",}}/><Avatarsize={50}person={{name: "Lin Lanying",imageId: "1bX5QH6",}}/></div>);
}
创建 src/utils.js
文件,里面编写工具类函数。
export function getImageUrl(person) {return "https://i.imgur.com/" + person.imageId + ".jpg";
}
GitHub提交记录
将内容嵌套在 JSX 标签中时,父组件将在名为 children 的 prop 中接收到该内容。例如,下面的 Card 组件将接收一个被设为 <Avatar />
的 children prop 并将其包裹在 div 中渲染。
创建 src/Avatar.jsx
文件,放置头像。
import { getImageUrl } from "./utils";export default function Avatar({ person, size }) {const defaultStyle = {borderRadius: "50%",padding: "5px",};return (<imgstyle={defaultStyle}className="avatar"src={getImageUrl(person)}alt={person.name}width={size}height={size}/>);
}
修改 src/Profile.jsx
文件,添加 Card 方法,注意参数传递了 children
,且在返回值中的 {children}
。
import Avatar from "./Avatar";function Card({ children }) {const cardStyle = {padding: "20px",borderRadius: "10px",boxShadow: "0 4px 8px rgba(0, 0, 0, 0.1)",backgroundColor: "#fff",};return <div style={cardStyle}>{children}</div>;
}export default function Profile() {return (<Card><Avatarsize={100}person={{name: "Katsuko Saruhashi",imageId: "YfeOqp2",}}/><Avatarsize={80}person={{name: "Aklilu Lemma",imageId: "OKS67lh",}}/><Avatarsize={50}person={{name: "Lin Lanying",imageId: "1bX5QH6",}}/></Card>);
}
条件渲染
GitHub提交记录
在 React 中,你可以通过使用 JavaScript 的 if 语句、&& 和 ? : 运算符来选择性地渲染 JSX。
创建 PackingList.jsx
文件,通过判断控制哪些事情已经完成。
function Item({ name, isPacked }) {let itemContent = name;if (isPacked) {itemContent = <del>{name + " ✅"}</del>;}return <li className="item">{itemContent}</li>;
}export default function PackingList() {return (<section><h1>Sally Ride 的行李清单</h1><ul><Item isPacked={true} name="宇航服" /><Item isPacked={true} name="带金箔的头盔" /><Item isPacked={false} name="Tam 的照片" /></ul></section>);
}
渲染列表
GitHub提交记录
从数组中过滤并渲染数据。
创建 src/data.js
文件,存放数组信息。
export const people = [{id: 0,name: "凯瑟琳·约翰逊",profession: "数学家",accomplishment: "太空飞行相关数值的核算",imageId: "MK3eW3A",},{id: 1,name: "马里奥·莫利纳",profession: "化学家",accomplishment: "北极臭氧空洞的发现",imageId: "mynHUSa",},{id: 2,name: "穆罕默德·阿卜杜勒·萨拉姆",profession: "物理学家",accomplishment: "关于基本粒子间弱相互作用和电磁相互作用的统一理论",imageId: "bE7W1ji",},{id: 3,name: "珀西·莱温·朱利亚",profession: "化学家",accomplishment: "开创性的可的松药物、类固醇和避孕药的研究",imageId: "IOjWm71",},{id: 4,name: "苏布拉马尼扬·钱德拉塞卡",profession: "天体物理学家",accomplishment: "白矮星质量计算",imageId: "lrWQx8l",},
];
创建 RenderList.jsx
文件,使用 filter
和 map
,过滤并展示出化学家的相关信息。注意给数组里面的每一项都指定一个 key
,进行唯一标识。
import { getImageUrl } from "./utils";
import { people } from "./data.js";export default function List() {const avatarStyle = {borderRadius: "50%",height: "100px",width: "100px",};const chemists = people.filter((person) => person.profession === "化学家");const listItems = chemists.map((person) => (<li key={person.id}><img style={avatarStyle} src={getImageUrl(person)} alt={person.name} /><p><b>{person.name}:</b>{" " + person.profession + " "}因 {person.accomplishment} 而闻名全世界!</p></li>));return <ul>{listItems}</ul>;
}
保持组件纯粹
- 一个组件必须是纯粹的,就意味着:
- 只负责自己的任务。 它不会更改在该函数调用前就已存在的对象或变量。
- 输入相同,则输出相同。给定相同的输入,组件应该总是返回相同的 JSX。
- 渲染随时可能发生,因此组件不应依赖于彼此的渲染顺序。
- 你不应该改变任何用于组件渲染的输入。这包括 props、state 和 context。通过 “设置” state 来更新界面,而不要改变预先存在的对象。
- 努力在你返回的 JSX 中表达你的组件逻辑。当你需要“改变事物”时,你通常希望在事件处理程序中进行。作为最后的手段,你可以使用 useEffect。
将 UI 视为树
GitHub提交记录
组件的一个主要特性是能够由其他组件组合而成。在 嵌套组件 中有父组件和子组件的概念,其中每个父组件本身可能是另一个组件的子组件。
下面我们使用 React 应用程序渲染一些鼓舞人心的引语。
修改 src/App.jsx
文件。
import "./App.css";
import FancyText from "./FancyText";
import InspirationGenerator from "./InspirationGenerator";
import Copyright from "./Copyright";function App() {return (<><FancyText title text="励志语录" /><InspirationGenerator><Copyright year={2025} /></InspirationGenerator></>);
}export default App;
创建 src/FancyText.jsx
文件,显示展示 “励志语录”。
export default function FancyText({ title, text }) {return title ? (<h1 className="fancy title">{text}</h1>) : (<h3 className="fancy cursive">{text}</h3>);
}
创建 src/InspirationGeneration.jsx
文件,显示主体部分。
import * as React from "react";
import quotes from "./quotes";
import FancyText from "./FancyText";export default function InspirationGenerator({ children }) {const [index, setIndex] = React.useState(0);const quote = quotes[index];const next = () => setIndex((index + 1) % quotes.length);return (<><p>你的励志名言是:</p><FancyText text={quote} /><button onClick={next}>再次激励我</button>{children}</>);
}
创建 Copyright.jsx
文件,显示版权。
export default function Copyright({ year }) {return <p className="small">©️ {year}</p>;
}
创建 quotes.js
文件,存放语录。
export default ["生活就像骑自行车,要保持平衡就得不断前进","每个人都是自己命运的建筑师","不要让别人的意见左右你的决定","人生的意义在于追求和实现自己的梦想",
];
总结
本篇文章,我们学习了 React 官方文档中讲述的 描述UI 的内容,总体上不算难,一些写法需要多加练习和记忆,下面文章我们学习 添加交互 部分。
好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!
参考资料:
- React 官方文档:React 官方文档
- DeepSeek:DeepSeek
- VS Code · Copilot