💥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;防抖节流优化输入框;阻止冒泡控制事件范围;自定义事件跨组件通信。把这张表贴在工位,面试再也不怕问事件绑定!


相关推荐
Larcher19 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐32 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭44 分钟前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu2 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端
六月的可乐2 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程