AI 全栈--reactjs 基础总结

目前使用AI开发,生成代码比较成熟的全栈组合前端是reactjs,所以这里整理一些reactjs 基础知识,方便生成reactjs 的时候,可以快速修改里面的代码。

本文档结合 React 官方文档编写,覆盖你日常开发中 80% 会用到的 React 概念。

你将学会

  • 如何创建和嵌套组件
  • 如何添加标记和样式
  • 如何显示数据
  • 如何渲染条件判断和列表
  • 如何响应事件和更新界面
  • 如何在组件间共享数据
  • React 核心原理与最佳实践

一、React 渲染原理

虚拟 DOM 的创建

React 使用 React.createElement 创建虚拟 DOM,返回值是 React 元素(虚拟 DOM):

javascript 复制代码
const element = React.createElement(
  'div',           // DOM 类型
  {               // DOM 属性
    style: {color: 'red'},
    className: 'container'
  },
  'hello',        // 子节点
  React.createElement("span", {style: {color: 'blue'}}, 'world')
);

JSX 语法

JSX 是 JavaScript 的语法扩展,最终会被 Babel 编译成 React.createElement 调用:

javascript 复制代码
let jsxElement = (
  <div style={{color:'red'}} className='container'>
    hello
    <span style={{color:'blue'}}>world</span>
  </div>
)

渲染方式

React 18 使用 createRoot API:

javascript 复制代码
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

二、创建和嵌套组件

React 应用由组件构成。组件是 UI 的一部分,拥有自己的逻辑和外观。React 组件是返回标记的 JavaScript 函数。

函数组件(推荐)

函数组件是一个返回虚拟 DOM 的函数:

javascript 复制代码
function MyButton() {
  return (
    <button>我是一个按钮</button>
  );
}

// 在其他组件中使用
export default function MyApp() {
  return (
    <div>
      <h1>欢迎来到我的应用</h1>
      <MyButton />
    </div>
  );
}

注意:React 组件名必须以大写字母开头,HTML 标签必须小写。

类组件(了解即可)

类组件继承自 React.Component,必须实现 render 方法:

javascript 复制代码
class ClassComponent extends React.Component {
  constructor(props) {
    super(props);  // 调用父类构造函数,this.props = props
  }
  render() {
    return <div>hello {this.props.name}</div>;
  }
}

现代 React 开推荐使用函数组件 + Hooks,类组件主要用于维护老项目。


三、JSX 语法

JSX 是 JavaScript 的扩展语法,让在 JS 中写 HTML 变得更容易。

JSX 规则

javascript 复制代码
// 1. 必须关闭所有标签
<br />

// 2. 必须有一个父元素包裹
function AboutPage() {
  return (
    <>
      <h1>About</h1>
      <p>Hello there.<br />How do you do?</p>
    </>
  );
}

// 3. 使用 className 而不是 class
<img className="avatar" />

在 JSX 中使用 JavaScript

使用花括号 {} 可以在 JSX 中嵌入 JavaScript 表达式:

javascript 复制代码
const user = { name: 'Hedy Lamarr', imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg', imageSize: 90 };

export default function Profile() {
  return (
    <>
      <h1>{user.name}</h1>
      <img
        className="avatar"
        src={user.imageUrl}
        alt={'Photo of ' + user.name}
        style={{
          width: user.imageSize,
          height: user.imageSize
        }}
      />
    </>
  );
}

提示style={{}} 不是特殊语法,而是 JSX 花括号内的一个普通对象。


四、添加样式

使用 className

javascript 复制代码
<img className="avatar" />
css 复制代码
/* CSS 文件 */
.avatar {
  border-radius: 50%;
}

使用内联样式

javascript 复制代码
<div style={{ color: 'red', fontSize: '16px' }}>
  红色文字
</div>

五、条件渲染

React 没有特殊的条件语法,使用普通的 JavaScript 条件语句。

方式一:if 语句

javascript 复制代码
let content;
if (isLoggedIn) {
  content = <AdminPanel />;
} else {
  content = <LoginForm />;
}

return <div>{content}</div>;

方式二:三元运算符(推荐)

javascript 复制代码
<div>
  {isLoggedIn ? <AdminPanel /> : <LoginForm />}
</div>

方式三:逻辑与 &&(无 else 分支时)

javascript 复制代码
<div>
  {isLoggedIn && <AdminPanel />}
</div>

六、列表渲染

使用 JavaScript 的 map() 函数渲染列表:

javascript 复制代码
const products = [
  { title: '卷心菜', isFruit: false, id: 1 },
  { title: '大蒜', isFruit: false, id: 2 },
  { title: '苹果', isFruit: true, id: 3 },
];

export default function ShoppingList() {
  const listItems = products.map(product =>
    <li
      key={product.id}
      style={{
        color: product.isFruit ? 'magenta' : 'darkgreen'
      }}
    >
      {product.title}
    </li>
  );

  return <ul>{listItems}</ul>;
}

重要 :每个列表项都需要唯一的 key 属性,帮助 React 识别哪些项目发生了变化。


七、响应事件

在组件内部声明事件处理函数来响应事件:

javascript 复制代码
function MyButton() {
  function handleClick() {
    alert('你点击了我!');
  }

  return (
    <button onClick={handleClick}>
      点击我
    </button>
  );
}

注意onClick={handleClick} 末尾没有括号!只传递函数引用,而不是调用它。React 会在用户点击时调用你的事件处理函数。

事件绑定方式

  • 冒泡阶段onClick
  • 捕获阶段onClickCapture

事件方法

  • event.stopPropagation() - 阻止事件传播
  • event.preventDefault() - 阻止默认行为(如 a 标签跳转)
javascript 复制代码
class EventDemo extends React.Component {
  childBubble(event) {
    console.log('子节点冒泡');
    event.stopPropagation();
  }

  clickLink = (event) => {
    event.preventDefault();
  }
}

事件执行顺序

React 事件系统和原生事件系统是独立的,执行顺序:

  1. React 捕获阶段
  2. React 冒泡阶段
  3. 原生捕获阶段
  4. 原生冒泡阶段

八、状态管理

组件使用**状态(State)**来"记忆"信息并显示它。

类组件状态

初始化状态

javascript 复制代码
// 方式1:在构造函数中
constructor(props) {
  super(props);
  this.state = { number: 0 };
}

// 方式2:类属性(推荐)
state = { number: 0 };

setState 更新状态

javascript 复制代码
// 对象方式
this.setState({ number: this.state.number + 1 });

// 函数方式(推荐,可基于旧状态计算新状态)
this.setState((prevState) => ({ number: prevState.number + 1 }));

// 带回调的 setState
this.setState(
  (prevState) => ({ number: prevState.number + 1 }),
  () => {
    console.log("State updated!", this.state.number);
  }
);

useState Hook

在函数组件中添加状态:

javascript 复制代码
import { useState } from 'react';

function MyButton() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      点击了 {count} 次
    </button>
  );
}
  • count:当前状态值
  • setCount:更新状态的函数
  • useState(0):初始值为 0

函数式更新(推荐)

当新状态依赖于旧状态时,使用函数式更新:

javascript 复制代码
function handleClick() {
  setCount(prevCount => prevCount + 1);
}

setState 的异步与批量更新

React 17

  • 异步批量更新 :在事件处理器、生命周期函数中,多个 setState 会被合并
  • 同步更新:在 setTimeout、Promise 等无法管理的场景中是同步的
javascript 复制代码
handleClick = () => {
  this.setState({ number: this.state.number + 1 });  // 批量合并
  console.log(this.state);  // 未更新
  this.setState({ number: this.state.number + 1 });  // 批量合并
  console.log(this.state);  // 未更新

  setTimeout(() => {
    this.setState({ number: this.state.number + 1 });  // 同步更新
    console.log(this.state);  // 已更新
  });
}

React 18

无论在什么场景,setState 都是批量的


九、Hooks 规则

  • 只在顶层调用:不要在循环、条件或嵌套函数中调用 Hooks
  • 只在 React 函数中调用:在 React 函数组件或自定义 Hook 中调用
javascript 复制代码
// ✅ 正确
function MyComponent() {
  const [count, setCount] = useState(0);
  // ...
}

// ❌ 错误
function MyComponent() {
  if (condition) {
    const [count, setCount] = useState(0); // 不要这样做
  }
}

十、组件间共享数据

问题:各自独立的状态

javascript 复制代码
// 每个按钮有自己独立的 count
function MyApp() {
  return (
    <div>
      <MyButton />
      <MyButton />
    </div>
  );
}

解决:提升状态

将状态提升到最近的共同父组件,通过 props 传递:

javascript 复制代码
export default function MyApp() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>计数器一起更新</h1>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  );
}

function MyButton({ count, onClick }) {
  return (
    <button onClick={onClick}>
      点击了 {count} 次
    </button>
  );
}

这就是"提升状态(Lifting State Up)"的概念。


十一、常用 Hooks 详解

useState - 状态管理

javascript 复制代码
const [count, setCount] = useState(0);

// 函数式更新
setCount(prevCount => prevCount + 1);

useReducer - 复杂状态管理

复杂状态管理,类似 Redux:

javascript 复制代码
const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'ADD':
      return { count: state.count + 1 };
    case 'MINUS':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const [state, dispatch] = useReducer(reducer, initialState);
dispatch({ type: 'ADD' });

useEffect - 副作用处理

处理副作用,替代类组件的生命周期:

javascript 复制代码
useEffect(() => {
  // 相当于 componentDidMount
  const timer = setInterval(() => {
    setCount(count => count + 1);
  }, 1000);

  // 返回清理函数,相当于 componentWillUnmount
  return () => {
    clearInterval(timer);
  };
}, []); // 空依赖数组 = 只执行一次

// 带依赖的 effect
useEffect(() => {
  // 当 count 变化时执行
  console.log('Count changed:', count);
}, [count]);

useContext - 跨组件共享数据

javascript 复制代码
const MyContext = createContext('defaultValue');

// 提供数据
<MyContext.Provider value="hello">
  <Child />
</MyContext.Provider>

// 消费数据
function Child() {
  const value = useContext(MyContext);
  return <div>{value}</div>;
}

useMemo - 缓存计算结果

javascript 复制代码
const displayData = useMemo(() => ({ count }), [count]);

useCallback - 缓存回调函数

javascript 复制代码
const incrementCount = useCallback(() => {
  setCount(count => count + 1);
}, [count]);

useRef - 引用 DOM

在函数组件中创建 ref:

javascript 复制代码
const inputRef = useRef(null);  // {current: null}

function focusInput() {
  inputRef.current.focus();
}

<input ref={inputRef} />

useImperativeHandle - 自定义 ref 暴露

自定义 ref 暴露给父组件的实例值:

javascript 复制代码
function FancyInput(props, ref) {
  const inputRef = useRef();

  useImperativeHandle(ref, () => ({
    focus() {
      inputRef.current.focus();
    }
  }));

  return <input ref={inputRef} />;
}

const ForwardFancyInput = forwardRef(FancyInput);

useLayoutEffect - 同步副作用

同步执行副作用,在 DOM 变更后同步调用(阻塞浏览器绘制):

javascript 复制代码
useLayoutEffect(() => {
  // 在浏览器绘制之前执行
  ref.current.style.transform = `translate(500px)`;
}, []);

十二、Ref 引用

createRef(类组件)

用于访问 DOM 元素或类组件实例:

javascript 复制代码
class RefComponent extends React.Component {
  inputRef = React.createRef(); // {current: null}

  handleButtonClick = () => {
    this.inputRef.current.focus();  // 访问真实 DOM
  }

  render() {
    return (
      <div>
        <input ref={this.inputRef} type="text" />
        <button onClick={this.handleButtonClick}>获得焦点</button>
      </div>
    );
  }
}

访问类组件实例

javascript 复制代码
class ParentComponent extends React.Component {
  childRef = React.createRef();

  handleClick = () => {
    this.childRef.current.alertMessage();  // 调用子组件方法
  }

  render() {
    return (
      <div>
        <ChildComponent ref={this.childRef}/>
      </div>
    );
  }
}

forwardRef(转发 ref)

函数组件默认不能接收 ref,需要使用 forwardRef

javascript 复制代码
function ChildComponent(props, forwardRef) {
  return <input ref={forwardRef}/>;
}

const ForwardChildComponent = React.forwardRef(ChildComponent);

十三、Context 上下文

用于跨组件层级共享数据,避免层层传递 props

创建 Context

javascript 复制代码
const MyContext = React.createContext('defaultValue');
const { Provider, Consumer } = MyContext;

使用 Context

Provider 提供数据

javascript 复制代码
<MyContext.Provider value={contextValue}>
  <ChildComponent/>
</MyContext.Provider>

Consumer 消费数据(函数组件)

javascript 复制代码
<MyContext.Consumer>
  {(value) => <div>{value}</div>}
</MyContext.Consumer>

类组件使用 contextType

javascript 复制代码
class MyClassComponent extends React.Component {
  static contextType = MyContext;
  render() {
    return <div>{this.context}</div>;
  }
}

多个 Context

javascript 复制代码
<BorderProvider value={borderValue}>
  <ColorProvider value={colorValue}>
    <ChildComponent />
  </ColorProvider>
</BorderProvider>

Context 嵌套规则

Consumer 会读取最近的 Provider 的值


十四、性能优化

shouldComponentUpdate

通过返回布尔值控制组件是否更新:

javascript 复制代码
shouldComponentUpdate(nextProps, nextState) {
  return nextState.number % 2 === 0; // 偶数才更新
}

PureComponent

自动进行浅比较,避免不必要的渲染:

javascript 复制代码
class PureComp extends React.PureComponent {
  render() {
    return <div>{this.props.value}</div>;
  }
}

React.memo

用于函数组件的记忆化:

javascript 复制代码
const MemoCounter = React.memo(Counter);

// 自定义比较函数
const MemoComp = React.memo(Comp, (prevProps, nextProps) => {
  return prevProps.value === nextProps.value;
});

性能优化最佳实践

javascript 复制代码
function App() {
  const [username, setUsername] = useState('zhufeng');
  const [count, setCount] = useState(0);

  // 缓存对象
  const displayData = useMemo(() => ({ count }), [count]);

  // 缓存回调函数
  const incrementCount = useCallback(() => {
    setCount(count => count + 1);
  }, []);

  return (
    <div>
      <input value={username} onChange={e => setUsername(e.target.value)} />
      <MemoChildButton displayData={displayData} incrementCount={incrementCount} />
    </div>
  );
}

十五、生命周期(类组件)

挂载阶段 (Mounting)

  1. constructor - 初始化状态
  2. componentWillMount (已废弃) - 组件将要挂载
  3. render - 计算虚拟 DOM(纯函数,不能有副作用)
  4. componentDidMount - 挂载完成,可发起网络请求

更新阶段 (Updating)

  1. componentWillReceiveProps - 收到新属性(已废弃)
  2. getDerivedStateFromProps - 从属性派生状态(静态方法)
  3. shouldComponentUpdate - 决定是否更新(性能优化关键点)
  4. getSnapshotBeforeUpdate - 获取 DOM 更新前的快照
  5. componentWillUpdate - 将要更新(已废弃)
  6. render - 重新计算虚拟 DOM
  7. componentDidUpdate - 更新完成

卸载阶段 (Unmounting)

  • componentWillUnmount - 清理操作(清除定时器、取消网络请求)

新生命周期方法示例

getDerivedStateFromProps

从 props 派生 state:

javascript 复制代码
static getDerivedStateFromProps(nextProps, prevState) {
  if (nextProps.itemCount !== prevState.itemCount) {
    return { itemCount: nextProps.itemCount };
  }
  return null; // 不更新状态
}

getSnapshotBeforeUpdate

获取 DOM 更新前的快照:

javascript 复制代码
getSnapshotBeforeUpdate(prevProps, prevState) {
  const list = this.listRef.current;
  return list.scrollHeight;  // 返回更新前的高度
}

componentDidUpdate(prevProps, prevState, snapshot) {
  const list = this.listRef.current;
  // 使用快照计算新的滚动位置
  list.scrollTop = list.scrollTop + (list.scrollHeight - snapshot);
}

十六、重要概念

合成事件 (SyntheticEvent)

React 实现的事件系统,与原生事件隔离,跨浏览器兼容。

批量更新 (Batching)

React 会将多个状态更新合并为一次渲染,提高性能。

受控组件与非受控组件

  • 受控组件:表单元素的值由 React state 控制
  • 非受控组件:表单元素的值由 DOM 自身控制

组件通信方式

  1. Props - 父子组件通信
  2. Callback - 子父组件通信
  3. Context - 跨层级通信
  4. Redux/Zustand - 全局状态管理
  5. Event Bus - 兄弟组件通信
  6. Ref - 直接访问子组件实例

学习路径建议

第一步:掌握基础

  • 组件与 JSX
  • Props 传递
  • 事件处理
  • useState Hook
  • 条件渲染和列表

第二步:深入理解

  • useEffect 副作用处理
  • 组件间通信
  • Context 使用
  • useRef 引用

第三步:进阶技能

  • 性能优化
  • 自定义 Hooks
  • 状态管理(useReducer)
  • 表单处理

第四步:实战项目

  • React Router 路由
  • Redux Toolkit / Zustand
  • React Query 数据请求
  • UI 组件库(Ant Design / Material-UI)

参考资源

相关推荐
我是ed2 小时前
# Vue3 图片标注插件 AILabel
前端
七月十二2 小时前
【TS】虚拟列表无渲染逻辑内核
前端
樊小肆2 小时前
ollmam+langchain.js实现本地大模型简单记忆对话-PostgreSQL版
前端·langchain·aigc
renke33642 小时前
Flutter 2025 模块化与微前端工程体系:从单体到可插拔架构,实现高效协作、独立交付与动态加载的下一代应用结构
前端·flutter·架构
wordbaby2 小时前
配置 Git Hooks:使用 Husky + lint-staged 自动代码检查
前端
得物技术2 小时前
Ant Design 6.0 尝鲜:上手现代化组件开发|得物技术
前端
孟祥_成都2 小时前
前端和小白都能看懂的 LangChain Model 模块核心实战指南
前端·人工智能
wordbaby2 小时前
配置 VS Code / Cursor 保存时自动格式化代码
前端
LYFlied2 小时前
Spec Coding:AI时代前端开发的范式革新
前端·人工智能·工程化·spec coding