react语法
1. jsx基本语法
1.1 渲染变量
vue的话是,在react中是{}
tsx
const name = "张三";
<div>
{name}
</div>1.2 样式的类名
不再使用class,而是className
tsx
const name = "张三";
<div className="active">
{name}
</div>插入变量的写法
tsx
// 手动拼接的问题:条件为false时会产生空字符串和多余空格
<div
className={
`container ${isActive ?
'active' : ''} ${isDisabled ?
'disabled' : ''}`}
>
</div>
// 如果isActive和isDisabled都是false,最终类名是 "container "(多余空格)需要用到clsx这个工具库
INFO
clsx 是一个轻量级(体积<1KB)、无依赖的 JavaScript 工具库,专门用于在 React(也可用于普通 JS)中条件性地拼接 CSS 类名。它的核心作用是简化 “根据不同条件动态生成类名” 的逻辑,避免手动拼接类名时出现的冗余空格、空字符串等问题,让类名管理更简洁、健壮。
jsx
import clsx from 'clsx';
<span
className={clsx(
isChild ? 'text-sm' : 'font-medium',
'hover:text-primary',
'cursor-pointer'
)}
>
{goodsInfo.title}
</span>1.3 内联样式
普通写法
tsx
const name = "张三";
<div className="active" style="{{color:'red'}}">
{name}
</div>
// 可以写成小驼峰加变量 style={{ backgroundColor: item.bgColor }}1.4 使用<></>当根标签
简单案例↓
tsx
const name = "张三";
< >
<div className="active" style="{{color:'red'}}">
{name}
</div>
</ >复杂案例
如果是一个界面渲染时的判断显示
tsx
{product.isActive && (
<>
<span className="text-sm text-black">{product.title}</span>
<span className="text-sm text-gray">{product.desc}</span>
<span className="text-sm text-gray">{product.create_time}</span>
</>
)}2.组件
2.1 类组件( 早期写法 )
React 16.8 之前的主流写法
tsx
// HelloWorldClass.tsx
import React, { Component } from 'react';
// 类组件:必须继承 React.Component,通过render返回内容
export default class HelloWorldClass extends Component {
// 核心方法:render是类组件的必备方法,返回可渲染的JSX
render() {
return (
<div style={{ padding: '20px', fontSize: '20px', color: '#666', marginTop: '20px' }}>
<h1>Hello World(类组件)</h1>
<p>这是React类组件的基础示例</p>
</div>
);
}
}2.2 函数组件
这是 React 16.8 + 推荐的写法,语法简洁
tsx
// HelloWorldFunction.tsx
import React from 'react';
// 函数组件:无状态基础版(最简洁的Hello World)
export default function HelloWorldFunction() {
// 返回JSX(React的模板语法),展示Hello World
return (
<div style={{ padding: '20px', fontSize: '20px', color: '#333' }}>
<h1>Hello World(函数组件)</h1>
<p>这是React函数组件的基础示例</p>
</div>
);
}- 函数式组件定义时首字母必须
大写 render渲染时必须使用标签
3 循环渲染列表
分为forEach渲染和map渲染,这俩也就是js数组方法
3.1 map渲染列表(最常用)
- 返回新数组:map 遍历数组时返回包含 JSX 的新数组,可直接嵌入 JSX 中渲染,语法极简;
- 纯函数特性:map 不修改原数组,返回新数组,符合 React“无副作用、数据不可变” 的设计理念;
- 适配 JSX 语法:JSX 中只能嵌入 “表达式”(变量、函数调用、数组等),map 返回的数组是合法表达式,而 forEach 无返回值(undefined)、filter 返回的是原数组子集(非 JSX),都无法直接满足。
tsx
import React from 'react';
// 极简map渲染:直接返回JSX数组
export default function MapRender() {
const list = ['Vue', 'React', 'Angular'];
return (
<ul>
{list.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}升级写法包含filter过滤
tsx
import React from 'react';
export default function FilterMapDemo() {
const list = ['HTML', 'CSS', 'JavaScript', 'React', 'Vue'];
return (
<ul>
{/* 第一步:filter筛选出包含"a"的元素;第二步:map渲染筛选后的结果 */}
{list
.filter(item => item.includes('a')) // 筛选:返回 ['JavaScript', 'React']
.map((item, index) => (
<li key={index}>{item}</li> // 渲染:仅显示这两个元素
))
}
</ul>
);
}高级写法
日常开发基本上就是写这种了
tsx
import React from 'react';
// 保持原有接口定义不变
interface Product {
id: number;
name: string;
price: number;
isDiscount: boolean;
}
export default function MapWithCondition() {
const productList: Product[] = [
{ id: 1, name: 'T恤', price: 99, isDiscount: true },
{ id: 2, name: '裤子', price: 199, isDiscount: false },
{ id: 3, name: '鞋子', price: 399, isDiscount: true },
];
return (
<div className="p-5"> {/* 替换内联padding: '20px' */}
<h3 className="text-lg font-medium mb-4">商品列表</h3> {/* 标题样式 */}
{/* map循环核心逻辑不变,仅替换样式类名 */}
{productList.map((product) => {
const finalPrice = product.isDiscount ? product.price * 0.8 : product.price;
let priceTag = '';
if (finalPrice < 100) {
priceTag = '平价';
} else if (finalPrice < 200) {
priceTag = '中端';
} else {
priceTag = '高端';
}
return (
<div
key={product.id}
className="p-2.5 my-2 border border-gray-200 rounded-md" // 替换商品卡片内联样式
>
<div className="mb-1">商品名称:{product.name}</div>
<div className="mb-1">原价:¥{product.price}</div>
<div className="mb-1">
最终价格:
{/* 条件判断样式类名:折扣价红色,原价默认黑色 */}
<span className={product.isDiscount ? 'text-red-600' : 'text-black'}>
¥{finalPrice}
</span>
{/* 折扣标签:ml-2 对应 marginLeft: '8px' */}
{product.isDiscount && <span className="ml-2">[8折]</span>}
</div>
<div>价格标签:{priceTag}</div>
</div>
);
})}
</div>
);
}INFO
注意,不知道你发现没有,前2个map循环都没写return
为什么这个复杂的写了循环呢?
注意箭头函数 =>{ } 的花括号
tsx
import React from 'react';
export default function ArrowMapDemo() {
const list = ['React', 'Vue', 'Angular'];
// 完整写法:带花括号 + return
const listFull = list.map((item, index) => {
return <li key={index}>{item}</li>;
});
// 简写一行:省略花括号 + 省略 return
const listShort = list.map((item, index) => <li key={index}>{item}</li>);
// 正常情况:有多行内容,需要加小括号包含div标签
const listShort2 = list.map((item, index) => (
<li key={index}>{item}</li>
...
));
return <ul>{listShort2}</ul>;
}它在循环体内,可以写变量,但是map循环需要return一个dom出去,花括号是必须的,加小括号是给return识别用的,不然不识别div这些。
3.2 forEach 渲染
注意forEach没有return返回值,直接写成上面那样会报错
这个items就是一个小型的子组件,基本不会去写forEach循环,谁写了要被笑话的
tsx
import React from 'react';
export default function ForEachRender() {
const list = ['HTML', 'CSS', 'JavaScript'];
const items = [];
list.forEach((item, index) => {
items.push(<li key={index}>{item}</li>);
});
// 直接渲染收集好的items数组
return <ul>{items}</ul>;
}4 组件实例
4.1 类组件class
经典count计数器
tsx
import React, { Component } from 'react';
// Class组件:通过this.state定义状态,this.setState修改状态
export default class ClassStateDemo extends Component {
// 1. 初始化state(类组件的状态必须放在this.state中)
state = {
count: 0, // 计数器初始值为0
};
// 2. 定义修改状态的方法(必须用箭头函数避免this指向问题)
increment = () => {
// 类组件必须用this.setState修改状态(不能直接赋值this.state.count++)
this.setState({ count: this.state.count + 1 });
};
decrement = () => {
this.setState({ count: this.state.count - 1 });
};
// 3. 渲染UI,通过this.state获取状态
render() {
return (
<div style={{ padding: '20px' }}>
<h3>Class组件 - 计数器</h3>
<p>当前计数:{this.state.count}</p>
<button onClick={this.increment} style={{ marginRight: '8px' }}>加1</button>
<button onClick={this.decrement}>减1</button>
</div>
);
}
}