react:事件处理

第七章:事件处理

React 实现了一个合成事件系统(SyntheticEvent),它是浏览器原生事件的跨浏览器包装器。

与原生事件的区别

  • 命名使用 camelCase:onClick 而非 onclick
  • 使用 JSX 表达式传入函数:onClick={handleClick} 而非 onClick=“handleClick()”
  • 不能通过 return false 阻止默认行为,必须显式调用 preventDefault

示例

// HTML
<button onclick="activateLasers()">激活激光</button>
 
// React
<button onClick={activateLasers}>激活激光</button>

阻止默认行为

// HTML
<a href="#" onclick="console.log('点击'); return false;">链接</a>
 
// React
function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('链接被点击');
  }
 
  return (
    <a href="https://example.com" onClick={handleClick}>
      点击我
    </a>
  );
}

绑定 this 的方法

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isToggleOn: true };
 
    // 方法 1:在构造函数中绑定
    this.handleClick = this.handleClick.bind(this);
  }
 
  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }
 
  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

其他绑定方法

class Toggle extends React.Component {
  state = { isToggleOn: true };
 
  // 方法 2:使用类属性语法(推荐)
  handleClick = () => {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  };
 
  // 方法 3:在 render 中使用箭头函数(不推荐,每次渲染都创建新函数)
  render() {
    return (
      <button onClick={() => this.handleClick()}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}
class List extends React.Component {
  handleClick = (id, event) => {
    console.log('ID:', id);
    console.log('Event:', event);
  };
 
  render() {
    return (
      <ul>
        {this.props.items.map(item => (
          // 方法 1:箭头函数
          <li key={item.id} onClick={(e) => this.handleClick(item.id, e)}>
            {item.name}
          </li>
 
          // 方法 2:bind(事件对象会自动传递)
          <li key={item.id} onClick={this.handleClick.bind(this, item.id)}>
            {item.name}
          </li>
        ))}
      </ul>
    );
  }
}

鼠标事件

function MouseEvents() {
  const handleClick = () => console.log('点击');
  const handleDoubleClick = () => console.log('双击');
  const handleMouseEnter = () => console.log('鼠标进入');
  const handleMouseLeave = () => console.log('鼠标离开');
  const handleMouseMove = (e) => console.log('移动:', e.clientX, e.clientY);
  const handleContextMenu = (e) => {
    e.preventDefault();
    console.log('右键菜单');
  };
 
  return (
    <div
      onClick={handleClick}
      onDoubleClick={handleDoubleClick}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
      onMouseMove={handleMouseMove}
      onContextMenu={handleContextMenu}
    >
      鼠标事件区域
    </div>
  );
}

键盘事件

function KeyboardEvents() {
  const handleKeyDown = (e) => {
    console.log('按下:', e.key, '键码:', e.keyCode);
    if (e.key === 'Enter') {
      console.log('回车键');
    }
    if (e.ctrlKey && e.key === 's') {
      e.preventDefault();
      console.log('Ctrl+S');
    }
  };
 
  const handleKeyUp = (e) => {
    console.log('释放:', e.key);
  };
 
  return (
    <input
      type="text"
      onKeyDown={handleKeyDown}
      onKeyUp={handleKeyUp}
    />
  );
}

表单事件

function FormEvents() {
  const handleChange = (e) => {
    console.log('值变化:', e.target.value);
  };
 
  const handleFocus = () => console.log('获得焦点');
  const handleBlur = () => console.log('失去焦点');
  const handleInput = (e) => console.log('输入:', e.target.value);
 
  return (
    <input
      type="text"
      onChange={handleChange}
      onFocus={handleFocus}
      onBlur={handleBlur}
      onInput={handleInput}
    />
  );
}

焦点事件

function FocusEvents() {
  const handleFocus = (e) => {
    console.log('焦点在:', e.target.name);
  };
 
  const handleBlur = (e) => {
    console.log('离开:', e.target.name);
  };
 
  return (
    <form>
      <input name="username" onFocus={handleFocus} onBlur={handleBlur} />
      <input name="password" onFocus={handleFocus} onBlur={handleBlur} />
    </form>
  );
}

React 的合成事件对象(SyntheticEvent)是对原生事件的跨浏览器包装。

常用属性

  • boolean bubbles
  • boolean cancelable
  • DOMEventTarget currentTarget
  • boolean defaultPrevented
  • number eventPhase
  • boolean isTrusted
  • DOMEventTarget target
  • number timeStamp
  • string type

常用方法

  • preventDefault() - 阻止默认行为
  • stopPropagation() - 阻止事件冒泡
  • persist() - React 17+ 已不需要,事件对象现在是持久的
function EventDemo() {
  const handleClick = (e) => {
    console.log('事件类型:', e.type);
    console.log('目标元素:', e.target);
    console.log('当前元素:', e.currentTarget);
    console.log('时间戳:', e.timeStamp);
 
    e.preventDefault();      // 阻止默认行为
    e.stopPropagation();     // 阻止冒泡
  };
 
  return <a href="/" onClick={handleClick}>点击</a>;
}

React 使用事件委托机制,所有事件都被委托到 document 或应用根容器(React 17+)。

优点

  • 减少内存消耗(不需要为每个元素绑定事件)
  • 动态添加的元素自动有事件处理

注意

  • 事件处理函数中的 event.target 是实际触发事件的元素
  • event.currentTarget 是绑定事件处理函数的元素

受控组件

function NameForm() {
  const [value, setValue] = useState('');
 
  const handleChange = (e) => {
    setValue(e.target.value);
  };
 
  const handleSubmit = (e) => {
    e.preventDefault();
    alert('提交的名字: ' + value);
  };
 
  return (
    <form onSubmit={handleSubmit}>
      <label>
        名字:
        <input type="text" value={value} onChange={handleChange} />
      </label>
      <input type="submit" value="提交" />
    </form>
  );
}

textarea

// HTML 中 textarea 的值通过子元素设置
// React 中通过 value 属性设置
 
function EssayForm() {
  const [value, setValue] = useState('请撰写关于你喜欢的事物的文章');
 
  return (
    <textarea
      value={value}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}

select

function FlavorForm() {
  const [value, setValue] = useState('coconut');
 
  return (
    <label>
      选择你喜欢的风味:
      <select value={value} onChange={(e) => setValue(e.target.value)}>
        <option value="grapefruit">葡萄柚</option>
        <option value="lime">酸橙</option>
        <option value="coconut">椰子</option>
        <option value="mango">芒果</option>
      </select>
    </label>
  );
}

处理多个输入

function ReservationForm() {
  const [state, setState] = useState({
    isGoing: true,
    numberOfGuests: 2
  });
 
  const handleChange = (e) => {
    const { name, type, checked, value } = e.target;
    setState({
      ...state,
      [name]: type === 'checkbox' ? checked : value
    });
  };
 
  return (
    <form>
      <label>
        参与:
        <input
          name="isGoing"
          type="checkbox"
          checked={state.isGoing}
          onChange={handleChange}
        />
      </label>
      <br />
      <label>
        来宾人数:
        <input
          name="numberOfGuests"
          type="number"
          value={state.numberOfGuests}
          onChange={handleChange}
        />
      </label>
    </form>
  );
}

非受控组件

function NameForm() {
  const inputRef = useRef(null);
 
  const handleSubmit = (e) => {
    e.preventDefault();
    alert('Name: ' + inputRef.current.value);
  };
 
  return (
    <form onSubmit={handleSubmit}>
      <input type="text" ref={inputRef} />
      <button type="submit">提交</button>
    </form>
  );
}

使用 useCallback 缓存事件处理函数

import { useCallback } from 'react';
 
function Parent() {
  const [count, setCount] = useState(0);
 
  // 每次渲染都创建新函数
  const handleClick1 = () => {
    setCount(c => c + 1);
  };
 
  // 只在依赖变化时创建新函数
  const handleClick2 = useCallback(() => {
    setCount(c => c + 1);
  }, []);
 
  return (
    <div>
      <Child onClick={handleClick1} />
      <Child onClick={handleClick2} />
    </div>
  );
}

避免在 render 中创建新函数

// 不推荐
function List({ items }) {
  return (
    <ul>
      {items.map(item => (
        <Item
          key={item.id}
          onClick={() => handleClick(item.id)}  // 每次渲染都创建新函数
        />
      ))}
    </ul>
  );
}
 
// 推荐
function List({ items }) {
  return (
    <ul>
      {items.map(item => (
        <ItemContainer key={item.id} item={item} />
      ))}
    </ul>
  );
}
 
function ItemContainer({ item }) {
  const handleClick = useCallback(() => {
    // 处理点击
  }, [item.id]);
 
  return <Item onClick={handleClick} />;
}

本章详细介绍了 React 的事件处理:

  • 合成事件系统
  • 事件绑定和 this 处理
  • 常用事件类型
  • 表单处理(受控和非受控组件)
  • 事件委托机制
  • 事件性能优化

事件处理是 React 开发的基础,掌握这些知识对于构建交互式应用至关重要。

该主题尚不存在

您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。

  • react/事件处理.txt
  • 最后更改: 2026/03/13 15:51
  • 张叶安