Skip to content

Latest commit

 

History

History
156 lines (98 loc) · 11.3 KB

08. Работа человека с интерфейсом через эвенты.md

File metadata and controls

156 lines (98 loc) · 11.3 KB

Работа человека с интерфейсом через эвенты

Интерфейс это не статичная картинка, но как понять что человек делает с ним?

Привет! Девятый урок и мы подбираемся к настоящему фронтэнду — передней части продукта, так сказать. Не вёрстке (пускай и на Реакте со СК и Роутером), а именно что фронтэнду.

Но для начала — пару обязательных технических знаний.

Дев тулз

Если вы уже начали экспериментировать с кодом, то вы, наверное, заметили, что вслепую сложно что-то делать.

Люди с курса по вёрстке знают про дев тулз — специальная утилита браузера, которая показывает дерево элементов и его стили.

Во всех современных браузерах (от Эджа до Хрома и Сафари) есть ДевТулз — инструменты разработчика. Обычно они делятся на кучу вкладок, но нас интересуют две: дерево элементов и консоль.

В консоль можно писать через функцию console.log().

Для Хрома и Файрфокса поставьте Реакт ДевТулз, тогда у вас будет доступ ещё и к компонентам с их стейтами и пропами. Удобно.

ДОМ или дерево элементов

На ДОМе (DOM, Document Object Model) построена вся работа браузеров. ДОМ, как вы понимаете, это дерево элементов, а Виртуал ДОМ — это технология, работающая с двумя деревами: она сравнивает их между собой и вычленяет маленькие изменения, чтобы экономно обновить ДОМ.

А как, кстати, работать с реальным ДОМом? Это же не магия какая-то, которая доступна только разработчикам библиотек типа Реакта. Веб вообще славится своей открытостью: всем доступно всё.

Работа с ДОМом императивна: вы должны указать "возьми этот элемент и сделай с ним что-нибудь".

Работа с элементами в Реакте декларативна: вы указываете "у этого элемента такие свойства".

Непонятно? Согласен. Давайте разбирать на примерах.

Эвенты

Если человек куда-то кликнул, проскроллил или ещё что-то сделал с интерфейсом, как это отследить? Как поставить хотя бы консоль.лог на это событие?

Событие! Вот как работает интерфейс: на событиях, эвентах. Произошло событие — мы должны его обработать. Как это лучше всего сделать? Наверное, функцией? Вызвать функцию когда произошло событие — это звучит логично.

Так оно и есть: когда происходит эвент, вызывается его хэндлер (обработчик). Хэндлер эвента это функция, в которую приходят аргументы, в этой функции мы делаем что-нибудь с эвентом, хоть консоль.логом выводим.

Судя по МДН, эвентов очень много, но мы будем рассматривать два простейших: клик по элементу и, допустим, фокус по инпуту.

Кстати, если вам интересно, почему я не перевожу термины — чтобы вам было проще с ними работать и гуглить информацию по ним.

Почитывая в прошлом Хабрахабр, я заметил идиотские переводы простейших терминов и не понимал даже как гуглить о чём идёт речь.

Работа с эвентами в браузерном Джсе

Как я и говорил, в браузерном Джсе мы работаем императивно: берём элемент и вешаем на него хэндлер.

<button id="my-button">click me</button>

<script>
  // ищем элемент через document.getElementById()
  // https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
  const button = document.getElementById("my-button");

  // вешаем на него клик
  button.addEventListener("click", function(event) {
    // при клике выводим в консоль данные эвента
    console.log(event);
  });
</script>

Скажем так, выглядит не очень удобно. А что если мы сможем указать прямо у элемента атрибут onClick и туда передать функцию?

И мы можем: существуют три вида работы с эвент хэндлерами и addEventListener как раз один из них.

Какой второй способ? Через атрибут onclick указать функцию и что в неё придёт:

<button onclick="handleMyButtonClick(event)">
  click me
</button>

<script>
  function handleMyButtonClick(event) {
    console.log(event);
  }
</script>

Выглядит уже намного лучше и понятнее, верно? Этот путь находится очень рядом с системой эвентов Реакта.

Работа с эвентами в Реакте

В примере выше есть несколько проблем:

  1. непонятный стиль кода вместо camelCase (onClick читается легче чем onclick),
  2. функция зачем-то передаётся как строка,
  3. функция как будто вызывается прямо в атрибуте, но на деле нет,
  4. нет системы ошибок: если забыл объявить handleMyButtonClick, то пользователь узнает об этом только при клике на кнопку, хотя Еслинт мог бы подсветить что такой функции нет.

Все четыре проблемы решил Реакт через лозунг "явное лучше неявного". С первым пунктом всё понятно, давайте пройдёмся по остальным трём.

Функция передаётся как функция, а не строка

Мы знаем, что в Джсхе мы можем выполнять любой Джс-код в {}: хоть {2+2}, хоть {getUserInfo(userId)}. Пропы тоже поддерживают этот синтаксис:

import React from "react";
import styled from "styled-components";

const Button = styled.button`
  // умножим размер на 10
  // чтобы получить размер паддингов
  padding: ${props => p.size * 10}px;
`;

<Button size={2 + 2}>Button of 4</Button>;

По этой причине мы на клик по кнопке можем передать функцию.

// Button.js
function handleClick(event) {
  console.log(event);
}

<button onClick={handleClick(event)}>click me</button>;

Но стоп! Стоп-стоп-стоп! Если мы так сделаем, откроем страницу, то даже без клика мы получим консоль.лог в браузере.

iframe: https://codesandbox.io/embed/k3kp4l0p8v

Как так?

Функция не должна вызываться в пропе

В проп должна передаться ссылка на функцию, а не её вызов.

// неправильно — вызовется сразу как компонент станет доступен
<button onClick={handleClick(event)}>click me</button>

// правильно — при клике на элемент вызовется эта функция
<button onClick={handleClick}>click me</button>

Как понять, что в Реакте приходит на этом onClick? Читайте официальную документацию: Handling Events и SyntheticEvent. Первая статья рассказывает о работе эвентов, вторая — о специальном типе данных SyntheticEvent, который отличается от дефолтного объекта браузера, который приходит в хэндлере эвента.

Четвёртая проблема, как вы понимаете, тоже решена: мы в Джсхе передаём обычный джаваскрипт, поэтому если наша функция не будет существовать, то Еслинт об этом расскажет — либо в редакторе (если вы настроили интеграцию), либо при сборке проекта (об этом в будущем).

Итог

В этом уроке мы не только разобрались с системой эвентов в Реакте и поняли чем она мощна, но и поработали с браузерными ДОМом и эвентами.

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

Кстати, как попрактиковаться в этих знаниях? Отловили мы эвент, дальше-то что? Узнаете в следующем уроке — там мы будем соединять стейт и эвенты.