【前端】【React】第三章:深入理解 React 事件处理与性能优化

七、React 事件处理与性能优化

React 事件处理采用 合成事件(SyntheticEvent),它是 React 对原生事件的封装,提供了更好的跨浏览器兼容性和性能优化。


(一)事件绑定

1. 基本事件绑定
jsx 复制代码
function Button() {
  return <button onClick={() => alert("Clicked!")}>Click Me</button>;
}
2. 在类组件中绑定事件
jsx 复制代码
class App extends React.Component {
  handleClick() {
    alert("Clicked!");
  }

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}

问题this.handleClick 没有绑定 this,导致 thisundefined
解决方案

  • 方法 1:使用箭头函数(推荐)

    jsx 复制代码
    <button onClick={() => this.handleClick()}>Click Me</button>
  • 方法 2:在构造函数中绑定 this

    jsx 复制代码
    constructor(props) {
      super(props);
      this.handleClick = this.handleClick.bind(this);
    }

(二)事件对象 event

React 事件处理函数会接收一个 合成事件(SyntheticEvent),它与原生事件类似,但性能更优。

jsx 复制代码
function Button() {
  const handleClick = (event) => {
    console.log(event.target); // 获取触发事件的元素
  };

  return <button onClick={handleClick}>Click Me</button>;
}
阻止默认行为
jsx 复制代码
function Link() {
  return (
    <a href="https://react.dev" onClick={(e) => e.preventDefault()}>
      Click me (but won't navigate)
    </a>
  );
}
事件冒泡 & 阻止事件传播
jsx 复制代码
function Parent() {
  const handleParentClick = () => console.log("Parent Clicked!");
  const handleChildClick = (event) => {
    event.stopPropagation(); // 阻止事件冒泡
    console.log("Child Clicked!");
  };

  return (
    <div onClick={handleParentClick}>
      <button onClick={handleChildClick}>Click Me</button>
    </div>
  );
}

(三)事件传参

传递参数
jsx 复制代码
function Button({ name }) {
  const handleClick = (name, event) => {
    console.log(`Hello, ${name}`);
  };

  return <button onClick={(e) => handleClick(name, e)}>Click Me</button>;
}

(四)性能优化

React 在事件处理上进行了优化,但仍需开发者手动优化。

1. 使用 useCallback 避免函数重复创建
jsx 复制代码
const handleClick = useCallback(() => {
  console.log("Clicked!");
}, []);
2. 使用 useMemo 避免不必要的计算
jsx 复制代码
const expensiveValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
3. 使用 React.memo 避免组件重复渲染
jsx 复制代码
const Child = React.memo(({ value }) => {
  console.log("Child Rendered");
  return <div>{value}</div>;
});
4. 使用 shouldComponentUpdate 进行类组件优化
jsx 复制代码
class Example extends React.Component {
  shouldComponentUpdate(nextProps) {
    return nextProps.value !== this.props.value;
  }
}

八、React 状态管理

React 的组件可以使用 useState 进行状态管理,但当组件层级较深时,状态管理会变得复杂。

(一)Context API(适用于全局状态共享)

1. 创建 Context
jsx 复制代码
const ThemeContext = React.createContext();
2. 提供数据
jsx 复制代码
function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}
3. 消费数据
jsx 复制代码
function Toolbar() {
  return (
    <ThemeContext.Consumer>
      {(theme) => <div>Current Theme: {theme}</div>}
    </ThemeContext.Consumer>
  );
}

推荐使用 useContext 简化写法

jsx 复制代码
function Toolbar() {
  const theme = useContext(ThemeContext);
  return <div>Current Theme: {theme}</div>;
}

(二)Redux(适用于大规模应用)

Redux 通过 单一数据源(Store)纯函数(Reducer) 管理应用状态。

1. 创建 Redux Store
jsx 复制代码
import { createStore } from "redux";

const reducer = (state = { count: 0 }, action) => {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    default:
      return state;
  }
};

const store = createStore(reducer);
2. 订阅 Store
jsx 复制代码
store.subscribe(() => console.log(store.getState()));
3. 触发 Action
jsx 复制代码
store.dispatch({ type: "INCREMENT" });
4. 结合 React

使用 react-redux 提供的 Provider

jsx 复制代码
import { Provider } from "react-redux";

function App() {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  );
}

九、React 18 重要优化

(一)自动批量更新(Automatic Batching)

React 18 以前,多个 setState 会触发多次渲染:

jsx 复制代码
setCount(count + 1);
setName("React");

React 18 之后,这些状态更新会自动合并,提高性能。


(二)并发渲染(Concurrent Rendering)

React 18 引入 并发模式,允许多个渲染任务同时进行,避免卡顿。

1. startTransition
jsx 复制代码
import { startTransition } from "react";

const handleInputChange = (e) => {
  startTransition(() => {
    setSearchQuery(e.target.value);
  });
};

(三)useDeferredValue(降低 UI 更新优先级)

jsx 复制代码
const deferredQuery = useDeferredValue(searchQuery);

React 会优先渲染 高优先级任务 (如输入框输入),而延迟更新 低优先级任务(如搜索结果)。


十、总结

1. 事件处理

  • 事件使用 合成事件
  • 可以通过 preventDefault 阻止默认行为
  • 事件处理函数应使用 useCallback 进行优化

2. 状态管理

  • 组件内部状态使用 useState
  • 组件间状态共享可使用 Context API
  • 大规模应用推荐 Redux

3. 性能优化

  • React.memo 避免组件重复渲染
  • useMemo 缓存计算值
  • useCallback 缓存事件处理函数

4. React 18 关键优化

  • 自动批量更新
  • 并发渲染
  • useDeferredValue 降低 UI 更新优先级

下一章:深入理解 React Router 及前端路由管理 🚀

相关推荐
柳杉4 小时前
从调研到闭环,我用 GPT-Image-2.5 和 GPT-6 Astra 把智慧厂房 3D 大屏这条链路走完了
前端·ai编程·数据可视化
芳心粽伙饭4 小时前
CSS第四章 布局
前端·css·html
CoderYanger4 小时前
Java EE 进阶:2.3 JavaScript 综合案例
java·前端·javascript·css·职场和发展·java-ee·html
摸鱼仙人~5 小时前
Vue 核心知识体系(大厂秋招方向)
前端·javascript·vue.js
ljt27249606615 小时前
Vue笔记--状态管理
前端·vue.js·笔记
benbenAItalk13 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
2601_9628857214 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
西瓜太郎123414 小时前
Claude Code、Codex CLI、Gemini CLI 能否共用一枚 Key?先看协议选择矩阵
前端·api 网关·claude code·gemini cli·codex cli
陈随易16 小时前
在Finch用了62亿词元,我认为这是新一代Agent工具之神
前端·人工智能·后端
水域安全老周16 小时前
水趣钓鱼救生衣专利拆解:两级锁紧如何解决落水人衣分离
java·前端·网络