DevGang
Авторизоваться

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

Как определить, какое действие будет предпринято при каждом событии

Работа c обработчиком событий React очень похожа на работу с событиями в элементах DOM. Хотя есть несколько отличий.

  • camelCase против строчных - onClick вместо onclick. Мы пишем обработчики событий React внутри фигурных скобок.
  • В случае React (JSX), вместо передачи строки, мы передаем функцию в качестве обработчика события. onClick={buttonClicked} вместо onclick=”buttonClicked()”
// React


// HTML

  • Другое отличие состоит в том, что для предотвращения поведения по умолчанию в React мы не можем возвращать false. Мы должны вызывать явно warnDefault.
// HTML


// React 
function handleClick(e) {
	e.preventDefault();
	console.log('Button clicked.');
}

return (
	

Аргумент события:

Обратите внимание на аргумент е. Он автоматически передается в обработчик всякий раз, когда происходит событие. И в зависимости от типа обработчика, иногда аргумент e имеет немного другой API (например, e.target.value против e.screenX).

Если вы не написали слишком много обработчиков событий раньше ... не беспокойтесь о запоминании различий! Вы начнете запоминать различные API e по мере их использования.

Привязки обработчиков событий

Прежде чем обсуждать привязки, давайте немного рассмотрим ключевое слово this. Ключевое слово this не определено по умолчанию в компонентах класса.

Так что в случае обычных функций ключевое слово this представляет объект, вызвавший метод. Этот вызывающий объект может быть чем угодно, например глобальным объектом window, кнопкой HTML или чем-то еще. Следовательно, ключевое слово this ДОЛЖНО представлять компонент, которому принадлежит метод.

Теперь вернемся к привязкам. У нас есть три способа привязки обработчиков событий.

1. Динамическое связывание:

Ниже мы будем вызывать .bind(this) в функции render().

class Button extends React.Component {
  buttonClicked() {
    alert("Button Clicked!");
  }

  render() {
    return ( 
   

{this.state.name}!

); } } ReactDOM.render(

Этот подход будет работать, однако проблема с этим подходом состоит в том, что любые изменения в this.state.name приведут к повторной визуализации компонента.

Это по очереди снова вызывает this.buttonClicked.bind(this) для привязки обработчика. В результате будет сгенерирован новый обработчик, который будет полностью отличаться от обработчика, используемого при первом вызове render().

Если на странице всего несколько кнопок, это еще допустимо, однако это плохая практика.

2. Связывание с конструктором:

В этом нет ничего особенного, это один из старых способов ведения дел, и он лучше, чем первый.

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.buttonClicked = this.buttonClicked.bind(this);
  }

  buttonClicked() {
    alert(this);
    /*
    Из-за привязки в функции конструктора 
    ключевое слово 'this' теперь ссылается на объект компонента 
    */
  }

  render() {
    return (
   

{this.state.name}!

); } } ReactDOM.render(

При таком подходе повторный вызов render() не будет генерировать новый обработчик для onClick(). Однако проблема в том, что это может легко стать утомительным.

Поскольку в этом подходе нам нужно использовать constructorsuper() и bind() для каждого отдельного обработчика, в конечном итоге это приведет к большому количеству повторяющегося кода. Чтобы решить эту проблему на помощь нам приходят стрелочные функции.

3. Использование стрелочных функций

ИМХО, такой подход, честно говоря, является лучшим способом ведения дел.

class Button extends React.Component {

  buttonClicked = () => {
    alert(this);
    /*
    Ключевое слово «this» относится к объекту компонента
    */
  }

  render() {
    return (
   	

{this.state.name}!

); } } ReactDOM.render(

В приведенном выше коде buttonClicked является функцией, которая эквивалентна: constructor() { this.buttonClicked = () => {…}; }

Следовательно, после инициализации компонента this.buttonClicked больше никогда не изменится. Таким образом, мы можем гарантировать, что повторное отображение  ); } } ReactDOM.render(

Привязка обработчика событий к 'this':

Первом аргументе должен ВСЕГДА быть this. Пример - Отправить «Button Clicked» в качестве параметра функции buttonClicked:

class Button extends React.Component {
  buttonClicked(a) {
    alert(a);
  }

  render() {
    return (
      
    );
  }
}

ReactDOM.render(

В приведенном выше примере, вместо использования this.buttonClicked.bind(this, “Button Clicked”), мы используем this.buttonClicked(this, “Button Clicked”), функция buttonClicked будет выполняться при загрузке страницы. Он не будет ждать нажатия кнопки.В обоих случаях аргумент ReactEvent - 'e' будет передан в качестве второго аргумента после значения. В случае стрелочной функции мы должны передать ее явно, однако с помощью bind() любые дальнейшие аргументы автоматически передаются.

Вывод

Мы можем использовать аналогичный подход при работе с событиями для элементов React, как при обработке событий на обычных элементах DOM. Есть несколько различий между ними, что, я думаю, мы можем легко иметь в виду.

Что касается привязок, всегда полезно использовать «Связывание стрелочных функций», когда это возможно.

Источник:

#React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

Напиши статью и выиграй годовую подписку на Яндекс плюс или лицензию от Jet Brains

Участвовать