react由Facebook团队推出,是目前前端生态中使用最广泛的视图库之一。它的核心思想是组件化和数据驱动视图:开发者只需要描述界面在某一数据状态下的样子,react负责把数据变化高效地渲染到页面上。要掌握react,首先要弄清楚它的基本语法体系,包括JSX、组件定义、props与state、事件处理、条件渲染和列表渲染等内容。本文将从这些基础语法入手,逐一讲解并给出代码示例,最后分析优缺点、适用场景和常见注意事项。

一、JSX语法:react的书写基础
JSX是react最具辨识度的语法特性,它允许在JavaScript代码中直接书写类似HTML的结构。需要明确的是,JSX并不是模板语言,它本质上会被Babel编译成React.createElement的调用,最终生成虚拟DOM对象。
JSX有几条必须遵守的规则。第一,JSX只能有一个根元素,如果不想产生多余的DOM节点,可以使用<Fragment>或者空标签<></>包裹。第二,在JSX中写JavaScript表达式需要用花括号{ },例如{user.name}、{count + 1}。第三,由于class是JavaScript的保留字,样式类名要写成className而不是class。第四,行内样式要传对象而不是字符串,且属性名采用驼峰命名。
function Welcome() {
const styles = { color: 'red', fontSize: '16px' };
const isLogin = true;
return (
<>
{/* JSX中的注释写法 */}
<h1 className="title" style={styles}>Hello React</h1>
<p>{isLogin ? '欢迎回来' : '请先登录'}</p>
</>
);
}上面这个例子覆盖了JSX的常见用法:空标签作为根元素、花括号嵌入表达式、className绑定类名、style绑定样式对象,以及三元表达式实现简单条件显示。
二、组件、props与state:数据与视图的组织方式
组件是react的基本构建单元。现代react开发以函数组件为主流,配合hooks管理状态;类组件在老项目中仍然常见,两者可以混合使用。组件名必须以大写字母开头,这是react区分组件和原生HTML标签的依据。
props是父组件传给子组件的只读数据,子组件内部不应该修改props,这是react的单向数据流原则。state则是组件内部的可变状态,通过useState创建,调用更新函数会触发组件重新渲染。
import { useState } from 'react';
// 子组件通过props接收数据
function UserCard(props) {
return <div className="card">姓名:{props.name},年龄:{props.age}</div>;
}
// 父组件管理状态并向下传递
function App() {
const [count, setCount] = useState(0);
return (
<div>
<UserCard name="张三" age={25} />
<button onClick={() => setCount(count + 1)}>点击了 {count} 次</button>
</div>
);
}这段代码展示了props的传递和state的基本用法。注意onClick中传入的是函数本身而不是函数调用结果,写成onClick={handleClick()}是初学者常见的错误,会导致函数在渲染时立即执行。
除了useState,常用的hooks还有useEffect,它用来处理副作用,例如数据请求、订阅事件、操作DOM等。它的第二个参数是依赖数组,传空数组表示只在挂载时执行一次,传入具体变量则在这些变量变化时重新执行。
useEffect(() => {
// 挂载后请求数据
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data));
return () => {
// 清理函数,组件卸载时执行
console.log('组件被卸载');
};
}, []);三、条件渲染、列表渲染与事件处理
react没有类似vue的v-if、v-for指令,条件渲染和列表渲染都靠原生JavaScript语法完成。条件渲染常用三元表达式、逻辑与运算符,或者直接用if语句提前return。
function Message({ messages }) {
return (
<div>
{messages.length > 0 ? (
<h3>你有 {messages.length} 条消息</h3>
) : (
<h3>暂无消息</h3>
)}
{messages.length > 0 && <p>请注意查收</p>}
</div>
);
}列表渲染使用数组的map方法,把数据数组转换成JSX元素数组。react需要每个元素提供唯一的key属性,帮助它识别哪些元素发生了变化,从而高效更新DOM。
function TodoList() {
const todos = [
{ id: 1, text: '学习react基础' },
{ id: 2, text: '练习hooks用法' },
{ id: 3, text: '完成项目实战' }
];
return (
<ul>
{todos.map(item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
);
}事件处理方面,react的事件是合成事件,命名采用驼峰形式,如onClick、onChange、onSubmit。在事件处理函数中访问事件对象,直接通过参数接收即可。
四、react的优缺点与适用场景
react的优点非常突出:组件化思想让代码高度可复用,虚拟DOM配合diff算法保证了较好的渲染性能,庞大的生态提供了丰富的第三方库和社区支持,跨端能力也让它能同时开发网页、移动端(react-native)和桌面端应用。
它的缺点同样需要正视:只是一个视图库,路由、状态管理、请求封装都需要自行搭配方案,不如Angular那样开箱即用;JSX和hooks的心智成本对新手不太友好,闭包陷阱、依赖数组等问题容易让人困惑;项目规模大时构建配置和状态管理方案的选型也有一定复杂度。
适用场景方面,react特别适合中大型Web应用、需要长期迭代维护的B端管理系统、对生态和跨端有要求的项目。如果是简单活动页或者对包体积极其敏感的场景,原生开发或轻量方案可能更合适。
五、常见问题与注意事项
key不要用数组索引。当列表发生插入、删除或排序时,用索引做key会导致状态错乱和渲染异常,应尽量使用数据中稳定唯一的id字段。
state更新是异步批处理的。连续多次调用setCount(count + 1)不会累加,因为count在本次渲染周期内不会变化。正确做法是使用函数式更新:setCount(prev => prev + 1)。
不要直接修改state。对于数组和对象类型的state,必须创建新引用再更新,例如用扩展运算符{...obj, name: 'new'},直接push或赋值不会触发重新渲染。
useEffect的依赖数组要写全。省略依赖可能导致读到旧值或产生无限循环渲染,建议开启eslint的react-hooks/exhaustive-deps规则来规避问题。
掌握以上这些基础语法和注意点,就具备了独立开发react中小型项目的能力。剩下的就是多写多练,在实践中逐步深入理解hooks原理和性能优化技巧。