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


相关推荐
叫我詹躲躲2 分钟前
n8n 自动化工作流平台完整部署
前端·langchain·领域驱动设计
遂心_2 小时前
为什么 '1'.toString() 可以调用?深入理解 JavaScript 包装对象机制
前端·javascript
IT_陈寒2 小时前
JavaScript 性能优化:5 个被低估的 V8 引擎技巧让你的代码快 200%
前端·人工智能·后端
王同学QaQ2 小时前
Vue3对接UE,通过MQTT完成通讯
javascript·vue.js
岛风风2 小时前
关于手机的设备信息
前端
小仙女喂得猪2 小时前
2025 Android原生开发者角度的React/ReactNative 笔记整理
react native·react.js
ReturnTrue8682 小时前
nginx性能优化之Gzip
前端
程序员鱼皮3 小时前
刚刚 Java 25 炸裂发布!让 Java 再次伟大
java·javascript·计算机·程序员·编程·开发·代码
w_y_fan3 小时前
Flutter 滚动组件总结
前端·flutter
wuli金居哇3 小时前
我用 Turborepo 搭了个 Monorepo 脚手架,开发体验直接起飞!
前端