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


相关推荐
li理1 分钟前
鸿蒙 Next 布局开发实战:6 大核心布局组件全解析
前端
EndingCoder2 分钟前
React 19 与 Next.js:利用最新 React 功能
前端·javascript·后端·react.js·前端框架·全栈·next.js
li理5 分钟前
鸿蒙 Next 布局大师课:从像素级控制到多端适配的实战指南
前端
前端赵哈哈8 分钟前
Vite 图片压缩的 4 种有效方法
前端·vue.js·vite
Nicholas6815 分钟前
flutter滚动视图之ScrollView源码解析(五)
前端
电商API大数据接口开发Cris17 分钟前
Go 语言并发采集淘宝商品数据:利用 API 实现高性能抓取
前端·数据挖掘·api
ITMan彪叔17 分钟前
Nodejs打包 Webpack 中 __dirname 的正确配置与行为解析
javascript·后端
风中凌乱的L22 分钟前
vue 一键打包上传
前端·javascript·vue.js
GHOME26 分钟前
Vue2与Vue3响应式原理对比
前端·vue.js·面试
张元清29 分钟前
useMergedRefs: 组件封装必不可少的自定义Hook
前端·javascript·面试