Обработка событий в React

Обработка событий элементов React похожа на обработку событий DOM-элементов. Однако есть некоторые синтаксические различия:

  • В React имена атрибутов привязки событий используют camelCase, а не нижний регистр.
  • При синтаксисе JSX нужно передавать функцию в качестве обработчика событий, а не строку (подход с DOM-элементами).

Обычный подход HTML:

<button onclick="activateLasers()">
  激活按钮
</button>

В React подход таков:

<button onClick={activateLasers}>
  激活按钮
</button>

Ещё одно отличие в React заключается в том, что нельзя использовать returnfalseдля предотвращения поведения по умолчанию; необходимо явно использоватьpreventDefault。

Например, в HTML мы обычно запрещаем ссылке по умолчанию открывать новую страницу так:
<a href="../index.html" onclick="console.log('点击链接'); return false">
  点我
</a>

В React подход таков:

function ActionLink() { function handleClick(e) { e.preventDefault(); console.log('Ссылка нажата'); } return ( <a href="#" onClick={handleClick}> Нажми меня </a> ); }

В примере e — это синтетическое событие.

При использовании React вам обычно не нужно использовать addEventListener, чтобы добавить обработчик к DOM-элементу после его создания. Вам нужно только указать обработчик, когда элемент изначально рендерится.

Когда вы определяете компонент с использованием синтаксиса классов ES6, обработчик события становится методом класса. Например, компонент Toggle ниже рендерит кнопку, которая позволяет пользователям переключать состояние переключателя:

Пример

class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; //Эта привязка необходима, чтобы `this` можно было использовать в функции обратного вызова 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> ); } } const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <Toggle />, document.getElementById('пример') );

Попробуйте »

В JSX-колбэках нужно быть осторожным с this. Методы класса по умолчанию не привязаны к this. Если вы забудете привязать this.handleClick и передадите его в onClick, значение this будет undefined при вызове функции.

Вообще, если вы не добавляете () после метода, напримерonClick={this.handleClick}, вам следует привязать this к этому методу.

Если использование bind вам мешает, есть два способа решить это. Если вы используете экспериментальный синтаксис инициализаторов свойств, вы можете использовать инициализаторы свойств, чтобы правильно привязать колбэки:

class LoggingButton extends React.Component { //Этот синтаксис гарантирует, что `this` привязан внутри handleClick //Это просто тест handleClick = () => { console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}> Нажми меня </button> ); } }

Если вы не используете синтаксис инициализаторов свойств, вы можете использовать стрелочные функции в обратном вызове:

class LoggingButton extends React.Component { handleClick() { console.log('это:', this); } render() { //Этот синтаксис гарантирует, что `this` привязан внутри handleClick return ( <button onClick={(e) => this.handleClick(e)}> Нажми меня </button> ); } }

Одна проблема с этим синтаксисом заключается в том, что при каждом рендеринге LoggingButton создаётся новая функция обратного вызова. В большинстве случаев это нормально. Однако если эта функция обратного вызова передаётся как prop дочерним компонентам, эти компоненты могут выполнять дополнительный повторный рендеринг. Обычно мы рекомендуем привязывать в конструкторе или использовать синтаксис инициализаторов свойств, чтобы избежать подобных проблем с производительностью.


Передача аргументов обработчикам событий

Обычно мы передаём дополнительные аргументы обработчикам событий. Например, если id — это id строки, которую вы хотите удалить, передать аргументы обработчику событий можно любым из следующих двух способов:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
Два приведённых выше подхода эквивалентны.

В двух приведённых выше примерах параметр e как объект события React будет передан вторым аргументом. При подходе со стрелочной функцией объект события должен передаваться явно, а при подходе с bind объект события и дополнительные аргументы будут передаваться неявно.

Стоит отметить, что при передаче аргументов функции-обработчику через bind для функции-обработчика, определённой в компоненте-классе, объект события e должен идти после переданных аргументов, например:

class Popper extends React.Component{ constructor(){ super(); this.state = {name:'Привет, мир!'}; } preventPop(name, e){ //Объект события e должен быть размещён последним e.preventDefault(); alert(name); } render(){ return ( <div> <p>привет</p> {/*Передавайте аргументы через метод bind().*/} <a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Нажмите</a> </div> ); } }
Другие расширения