💥React 事件绑定与响应:从“懵圈”到“秒懂”,附 5 个实战技巧

面试官:"React 事件绑定怎么写?"

你:"onClick={this.handleClick}。"

面试官:"this 指向呢?"

你:"......"

别怕,今天把 React 事件绑定的坑全填掉!


一、React 事件绑定:3 种写法

1️⃣ 绑定方法(类组件)

jsx 复制代码
class Demo extends React.Component {
  handleClick = () => {
    console.log('Clicked!');
  };

  render() {
    return <button onClick={this.handleClick}>Click me</button>;
  }
}
  • 箭头函数 :自动绑定 this,最省心。

2️⃣ 绑定实例方法(类组件)

jsx 复制代码
class Demo extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log('Clicked!');
  }

  render() {
    return <button onClick={this.handleClick}>Click me</button>;
  }
}
  • bind:在构造函数里绑定,适合普通函数。

3️⃣ 函数组件 + 事件处理

jsx 复制代码
function Demo() {
  const handleClick = () => {
    console.log('Clicked!');
  };

  return <button onClick={handleClick}>Click me</button>;
}
  • 函数组件:直接定义函数,简洁明了。

二、事件对象:e 是谁?

jsx 复制代码
function handleChange(e) {
  console.log(e.target.value); // 拿到输入框的值
}

function Demo() {
  return <input onChange={handleChange} />;
}
  • e合成事件对象,类似原生事件,但跨浏览器。

三、事件委托:少写 80% 的绑定代码

jsx 复制代码
function Demo() {
  const handleChildClick = (id) => {
    console.log(`Child ${id} clicked`);
  };

  return (
    <ul onClick={(e) => handleChildClick(e.target.dataset.id)}>
      <li data-id="1">Item 1</li>
      <li data-id="2">Item 2</li>
    </ul>
  );
}
  • 利用 e.target,在父级统一处理子级事件。

四、防抖节流:输入框的性能救星

防抖(Debounce)

jsx 复制代码
function useDebounce(callback, delay) {
  const timer = useRef(null);

  const debouncedCallback = useCallback((...args) => {
    clearTimeout(timer.current);
    timer.current = setTimeout(() => callback(...args), delay);
  }, [callback, delay]);

  return debouncedCallback;
}

function Demo() {
  const handleChange = useDebounce((e) => {
    console.log('Typing:', e.target.value);
  }, 500);

  return <input onChange={handleChange} />;
}

节流(Throttle)

jsx 复制代码
function useThrottle(callback, limit) {
  const lastCall = useRef(Date.now());

  const throttledCallback = useCallback((...args) => {
    const now = Date.now();
    if (now - lastCall.current >= limit) {
      callback(...args);
      lastCall.current = now;
    }
  }, [callback, limit]);

  return throttledCallback;
}

function Demo() {
  const handleChange = useThrottle((e) => {
    console.log('Typing:', e.target.value);
  }, 500);

  return <input onChange={handleChange} />;
}

五、事件穿透:阻止冒泡,让父级"看不见"

jsx 复制代码
function Demo() {
  const handleClick = (e) => {
    e.stopPropagation(); // 阻止冒泡
    console.log('Inner clicked');
  };

  const handleOuterClick = () => {
    console.log('Outer clicked');
  };

  return (
    <div onClick={handleOuterClick}>
      Outer
      <div onClick={handleClick}>Inner</div>
    </div>
  );
}

六、自定义事件:给组件加"私有信号"

jsx 复制代码
const EventEmitter = () => {
  const listeners = useRef({});

  const on = (eventName, callback) => {
    listeners.current[eventName] = listeners.current[eventName] || [];
    listeners.current[eventName].push(callback);
  };

  const emit = (eventName, ...args) => {
    const eventListeners = listeners.current[eventName] || [];
    eventListeners.forEach((listener) => listener(...args));
  };

  return { on, emit };
};

function Child() {
  const { emit } = useContext(EventEmitterContext);

  const handleCustomEvent = () => {
    emit('customEvent', 'Hello from Child!');
  };

  return <button onClick={handleCustomEvent}>Trigger Custom Event</button>;
}

function Parent() {
  const { on } = useContext(EventEmitterContext);

  useEffect(() => {
    on('customEvent', (message) => {
      console.log('Custom event received:', message);
    });
  }, [on]);

  return <Child />;
}

七、总结:React 事件绑定速记卡

场景 写法
类组件绑定 this.handleClick = this.handleClick.bind(this); 或箭头函数
函数组件 const handleClick = () => { ... };
事件对象 e.target.value 拿值
事件委托 e.target.dataset.id 读属性
防抖 useDebounce(callback, delay)
节流 useThrottle(callback, limit)
阻止冒泡 e.stopPropagation()
自定义事件 emit('eventName', data) + on('eventName', callback)

🏁 一句话总结

React 事件绑定:类组件用箭头函数或 bind,函数组件直接定义;事件对象用 e.target;防抖节流优化输入框;阻止冒泡控制事件范围;自定义事件跨组件通信。把这张表贴在工位,面试再也不怕问事件绑定!


相关推荐
哈__5 分钟前
React Native 鸿蒙跨平台开发:StatusBar 状态栏组件
javascript·react native·react.js
C_心欲无痕21 分钟前
nginx - 核心概念
运维·前端·nginx
开开心心_Every25 分钟前
安卓做菜APP:家常菜谱详细步骤无广简洁
服务器·前端·python·学习·edge·django·powerpoint
前端_Danny27 分钟前
用 ECharts markLine 实现节假日标注
前端·信息可视化·echarts
古城小栈29 分钟前
Rust 丰富&好用的 格式化语法
前端·算法·rust
丢,捞仔39 分钟前
uni-app上架应用添加权限提示框
前端·javascript·uni-app
Glink44 分钟前
从零开始编写自己的AI账单Agent
前端·agent·ai编程
Hilaku1 小时前
我是如何用一行 JS 代码,让你的浏览器内存瞬间崩溃的?
前端·javascript·node.js
努力犯错玩AI1 小时前
如何在ComfyUI中使用Qwen-Image-Layered GGUF:完整安装和使用指南
前端·人工智能
Lefan1 小时前
在浏览器中运行大模型:基于 WebGPU 的本地 LLM 应用深度解析
前端