О чувак. На моей работе на прошлой неделе я был плохим разработчиком. Я просто подумал: «К черту все, эта неделя — моя неделя. Нет больше CSS. Я собираюсь сделать что-то супер классное». Расскажите о знаменитых последних словах. Но мне было все равно! Я собирался изменить мир вокруг себя к лучшему.
Проблема:
Нам нужен был пользовательский интерфейс, в котором мы хотели создать среду, в которой щелчок в бесцельном месте внутри нее оказывал бы определенное влияние на определенные компоненты. Приложения для такого рода систем включают в себя открытие и закрытие раскрывающихся списков, выполнение одной функции любого типа, когда пользователь выполняет такое поведение.
Это не то, что я могу сделать только с помощью CSS. Я был вне себя от радости. Я услышал слабый зов сирены в каком-то отрывке из книги Дугласа Крокфорда JavaScript: The Good Parts. Он сказал: «Давайте делегируем события!».
Что мне нужно было сделать, чтобы воплотить в жизнь мои самые смелые мечты и сделать что-то вроде старого JavaScript?
На самом высоком уровне мне просто нужно было найти способ решить, пытается ли пользователь щелкнуть кнопку или просто пробует поведение «щелчка», которое люди используют по умолчанию при навигации по веб-сайтам. Я - фанат. Я всегда делаю это поведение щелчка. Я думаю, что тот, кто первым придумал этот пользовательский опыт, — гений. Если пользователь чувствует разочарование, пытаясь ориентироваться в новом для него пользовательском интерфейсе, просто случайный щелчок может помочь ему легко добраться туда, куда он хочет.
Сначала я остановился на утилите, которая буквально сохраняла ссылки на разные методы, кэшируя их в легкодоступных местах, а также прикрепляла прослушиватели событий к документу, указанному через API. Затем события, пойманные в этих прослушивателях, которые содержат информацию, идентифицирующую элемент, из которого было инициировано событие, затем использовались для выполнения соответствующих методов. Обратный вызов — отличный способ описать, как обрабатывались эти методы. Частью делегирования событий был JavaScript. Обратные вызовы, которые они контролировали, устанавливали состояние в некоторых компонентах React.
Это сработало! Хотя это было действительно сложно. Я также децентрализовал свое состояние, помещая важные его части во что-то, что не было утилитой, это была опухоль, выскакивающая сбоку от этого компонента React. Чистое делегирование событий никогда не будет работать хорошо, когда речь идет о взаимодействии системы событий React и фактической системы событий DOM. У вас не может быть цельных частей состояния, циркулирующих в разных потоках данных. Время от времени они будут конфликтовать и портить вам жизнь раздражающими ошибками. Я слишком много раз учился на собственном горьком опыте. Клянусь, на этот раз я остановлюсь по-настоящему.
Вторая итерация была лишь немного круче. Это позволило компонентам React, в которых размещались раскрывающиеся списки, которые я хотел переключить на «щелкнуть», обрабатывать действия, контролируемые пользователем. По крайней мере, это свело к минимуму количество событий, происходящих в DOM, сеющих хаос и разрушающих жизни. Моя жизнь стала намного лучше. Код стал намного проще. Хотя минусов было предостаточно. Мне пришлось придумать способ делать щелчки внутри компонентов, способных «щелкнуть», а не закрывать их родителей. Я прибегнул к созданию своего рода белого списка, и это было нормально.
Делегат событий Mixin
После долгих обзоров кода последняя итерация была полностью сосредоточена внутри транспортного средства, которым является React. Я отлично поиграл с детским реквизитом React и передал реквизит детям. Это был взрыв! Это был просто хитрый компонент React, который в своем приложении обертывал другой компонент и наделял его сверхспособностями по обработке событий. Слушатель верхнего уровня застрял в своем методе рендеринга и содержал несколько массивов обернутых обратных вызовов с состоянием, которые вызывали или не вызывали поведение в раскрывающемся списке или выделяли div (все мои варианты использования).
````
````
Это сработало отлично! Тоже было солидно! Я был просто поражен своей личной гениальностью. Идея была проста, и я победил. Я добрался до вершины своей внутренней горы. Я должен сделать буквально все! Я включу его репродукцию в будущем. Я, честно говоря, немного разочарован тем, что не додумался сделать это с самого начала. В прошлом я тупо пытался объединить две разные системы, управляемые событиями. Это вызвало ненужные и случайные ошибки. И все знают, что именно эти случайные ошибки будут там, где ваше приложение умирает ранней смертью. Не делай этого. Вы предупреждены.
К сожалению, замечательные дополнительные вещи React (использование дочерних реквизитов, передача реквизитов от родителя к дочерним элементам, компоновка компонентов для создания суперкомпонентов…) рассматривались как ненужная чепуха. Мне также сказали, что хранить такое количество состояния в другом месте, а не все остальное состояние, было плохой идеей. Я могу с этим согласиться. Как человек, который работает над приложением, которое когда-то казалось мне абсолютно бездонным (то есть все, что я делаю, это тыкаю в устаревший код), чем меньше сюрпризов вы добавляете в кодовую базу, тем дольше жизнь вашего кода.
Это было очень весело, чтобы сделать, хотя. Я думаю, что то, как миксин был построен, могло быть стабильным. Несмотря ни на что, мне пришлось внести имена классов в белый список. Я действительно не знаю, что еще нужно сделать, чтобы помочь делегатору событий различать события, которые были вызваны случайными и преднамеренными кликами, без использования прослушивателя.