2、前端基础(一):React核心概念(JSX、组件、Props、State)、创建第一个React应用
好,咱们正式开始前端部分。说实话,很多同学学全栈最怕的就是前端,觉得又要学HTML又要学CSS还要学JS,头都大了。但React的出现,其实把前端开发的门槛降了一大截。你想想看,以前写个页面要手动操作DOM,改个数据得先找到元素再更新,麻烦得很。React直接告诉你:别管DOM了,你只管数据,剩下的交给我。
我个人习惯把React理解成一个「状态机」。你的页面长什么样,完全取决于当前的数据状态。数据变了,页面自动跟着变。这个思路一旦建立起来,后面学什么都会顺很多。
JSX:在JavaScript里写HTML
先说说JSX。这东西刚出来的时候争议挺大的,很多人觉得「这不就是把HTML混进JS里了吗?开倒车啊!」。但我第一次用的时候,反而觉得挺自然。你想想,一个按钮的样式、行为、结构本来就是一体,硬拆成三个文件才奇怪吧?
JSX其实就是JavaScript的语法扩展。它允许你在JS文件里写类似HTML的标签:
const element = <h1>Hello, React!</h1>;
看着像HTML,但本质上是JS。浏览器不认识JSX,所以需要Babel这类工具把它转成 React.createElement() 调用。不过这些底层细节你暂时不用操心,脚手架都帮你配好了。
核心规则:JSX里只能有一个根元素。如果有多个并列标签,必须用 <div> 或者 <React.Fragment>(简写 <></>)包起来。
还有几个小细节要注意:
- class 要写成 className(因为class是JS保留字)
- style 接收一个对象,不是字符串:
style={{ color: 'red' }} - 花括号
{}里可以写任何JS表达式
我的习惯:刚开始写JSX时,容易忘记花括号。记住一个口诀:遇到JS逻辑就加花括号。变量、函数调用、三元表达式,统统包进去。
组件:页面的积木块
组件是React的核心思想。说白了,就是把页面拆成一个个独立的小块,每个块只管自己的事。我做过一个后台管理系统,光表格就有七八种变体。如果每个页面都单独写一遍,维护起来简直是噩梦。后来我把表格抽成组件,传不同的配置进去就行,省了至少一半的代码量。
React里组件有两种写法:
函数组件(推荐):
function Welcome(props) {
return <h1>你好,{props.name}</h1>;
}
类组件(旧写法):
class Welcome extends React.Component {
render() {
return <h1>你好,{this.props.name}</h1>;
}
}
现在新项目基本都用函数组件了。类组件你了解就行,面试偶尔会问到,但实际开发中我建议直接用函数组件加Hooks。
注意:组件名必须大写开头。React会区分小写开头的标签(原生HTML)和大写开头的标签(自定义组件)。我见过新手因为这个bug排查了半天,嗯,我自己也犯过。
Props:组件之间的传话筒
Props就是组件的参数。父组件给子组件传数据,全靠它。而且Props是只读的——你绝对不能在里面修改props的值。为什么?因为数据流是单向的,从父到子,改数据只能由父组件来做。
// 父组件
function App() {
return <User name="张三" age={25} />;
}
// 子组件
function User(props) {
return (
<div>
<p>姓名:{props.name}</p>
<p>年龄:{props.age}</p>
</div>
);
}
这里有个小技巧:可以用解构让代码更清爽:
function User({ name, age }) {
return (
<div>
<p>姓名:{name}</p>
<p>年龄:{age}</p>
</div>
);
}
避坑指南:我曾经在项目里把props直接赋值给state,结果数据不同步了。记住,props是父组件的数据快照,不要试图在子组件里「缓存」它,除非你真的知道自己在做什么。
State:让组件活起来
Props是外部传入的,State是组件自己管理的。State变了,组件自动重新渲染。这就是React最核心的「响应式」机制。
在函数组件里,我们用 useState 这个Hook来管理状态:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>你点击了 {count} 次</p>
<button onClick={() => setCount(count + 1)}>点我</button>
</div>
);
}
注意几个要点:
useState返回一个数组,第一个是当前值,第二个是更新函数- 更新State要用set函数,直接修改count不会触发重新渲染
- State更新是异步的,连续调用setCount(count + 1)两次,只会加一次
为什么是异步?React会把多个setState合并成一次更新,提高性能。所以如果你依赖前一个状态来更新,要用函数形式:setCount(prev => prev + 1)
创建第一个React应用
好,理论说完了,咱们动手创建一个真正的React项目。我建议用Vite,比Create React App快得多:
npm create vite@latest my-first-react-app -- --template react
cd my-first-react-app
npm install
npm run dev
几秒钟后,浏览器打开 http://localhost:5173,你就能看到React的默认页面了。
项目结构很简单:
| 文件/目录 | 作用 |
|---|---|
| src/main.jsx | 入口文件,渲染根组件 |
| src/App.jsx | 根组件,你主要在这里写代码 |
| src/App.css | 样式文件 |
| index.html | HTML模板,Vite会注入JS |
打开 src/App.jsx,把里面的内容替换成我们刚才写的Counter组件:
import { useState } from 'react';
import './App.css';
function App() {
const [count, setCount] = useState(0);
return (
<div className="App">
<h1>我的第一个React应用</h1>
<p>你点击了 {count} 次</p>
<button onClick={() => setCount(count + 1)}>
点我
</button>
</div>
);
}
export default App;
保存文件,浏览器会自动刷新。点击按钮,数字就会变化。恭喜你,第一个React应用跑起来了!
我的建议:刚开始别急着学太多API。先把JSX、组件、Props、State这四个概念玩熟。我见过太多人一上来就啃Redux、React Router,结果基础没打牢,后面越学越乱。先把Counter改成Todo List,再改成留言板,一步步来。
嗯,这一章的内容就到这。下一章我们会深入React的组件通信和生命周期,到时候你会发现自己对React的理解又上了一个台阶。