Legacy на фронте и моя победа над ним

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Всем Привет! Хочу поделиться своим опытом работы с огромным и непонятным legacy кодом на фронте. Я не специалист в работе с чистым JS и возможно мой подход был совсем не верным, поэтому просьба оставлять аргументированные комментарии, буду благодарен.

Наш проект написан на шаблонах PHP Yii2, на фронте повсеместно используется всеми не любимый jQury. Перед мной стояла задача реализовать динамическую отрисовку элемента, при добавлении N - стиля на элемент родителя. Основная проблема с которой мне пришлось столкнуться, это работа с DOM-деревом. В проекте используются шаблоны и дополнительные виджеты, то классы стилей на странице могут дублироваться. И логика работы виджетов прописана на глобальном уровне, что влечет за собой сложность простого обращения к элементам с использованием jQuery. В примерах использовал функциональный подход, потому что есть вероятность использования в старых браузерах.

Пример:

<div class="clear">
    <div class="select-item">
        <?= $form->field($model, 'place_work')->textInput()->label();?>
    </div>
</div>

В ТЗ обязательным пунктом было, что добавление стиля должно было включать определенную логику при добавлении элемента. При этом сам элемент должен обладать доп. функционалом, опять же мы упираемся на глобальное DOM-дерево на странице. Поэтому добавлять уникальный ID мы не можем, тем более что данный класс может добавляться с помощью Ajax запросов, а это тянет за собой тоже определенные сложности.

Перечитав множество статей и руководств, решил попробовать атомарно работать с родительским элементом, таким образом мы изолируем от общего DOM, что позволяет управлять его детьми без нарушения целостности страницы. При обращении jQuery к элементам DOM, нам возвращается объект. Используя наследование, мы можем расширить функционал, либо изменять текущий элемент.

Пример реализации вставки input поиска в выпадающее меню:

$(function () {
    if ($('div').hasClass('test')) {
        const test = $('.my-class');

        for (let obj of test) {
            new GenerateObj($(obj));
        }
    }
});


function GenerateObj(obj){
    if((typeof obj) === "object" && obj != undefined){
        this.__proto__ = obj;
    } else {
        console.warn("Дружок, что то не так.")
    }
}

Первая функция срабатывает в тот момент когда DOM-дерево было построено и производим поиск нужного нам класса в DOM. При дублировании классов стилей на странице jQuery возвращает массив объектов с заданным стилем. При вызове ключевого слова new мы создаем объект функции, которая аргументом принимает в себя объекты от которых мы будем наследоваться и с которыми будем работать.

function GenerateObj(obj){
  // Инициализация из примера выше.
  // Какая то дополнительная логика. 
  this._createInput = function(object){
      // Функция для вставки элемента в страницу. 
      // Описываем элемент кторый нужно вставить в DOM. 
          const input = $(`<li class="input">` +
              `<input type="search" id="input" class="text-input" placeholder="Мой элемент"/>` +
              `</li>`);
          $(input).prependTo(object.find(".selectric ul"));
      }
  //Вызов метода, так как я расширяю функционал отрисовку делал в конструкторе.
  //Если есть потребность то проще вынести в отдельный метод вызов всей логики.
  this.__createInput(this);
}

А вот теперь самый интересный момент объясняющий почему пришлось использовать данный подход.

function GenerateObj(obj){
  // Инициализация из примера выше.
  // Какая то дополнительная логика. 
  this.__createOnClick = function(obj){
      //метод отслеживающий событие щелчка мыши по элементу. 
          obj.find(".input").on('click', function(event){
              event.stopPropagation();
            
              return obj.find(".selectric-wrapper").addClass(function(e){
                  if(this===e){
                      return "selectric-open";
                  } else {
                      return "selectric-below";
                  }
              });
        });
    }

  //Какой то еще код. 
  this.__createOnClick(this);
}

Данный метод отслеживает щелчок мыши по элементу, останавливает логику глобальных стилей и логики. Без данного метода при нажатии элементов ( в нашем случае <li>) внутри родителя ( <ul> ) происходило закрытие выпадающего списка. Так как мы вставили input и нам нужно на него нажать, что бы ввести текст по которому необходимо провести поиск. То при дефолтном глобальном поведении при нажатии по input происходило закрытие выпадающего списка, поэтому мы отменяем глобальную обработку данного события, и передаем в родительский элемент класс описывающий его поведение при нажатии на дочерний элемент.

Все вроде просто, но черт кроется в деталях. Если на странице повторяются стили и элементы с которыми мы работаем, то если мы не производим изоляцию объекта и не работаем с ним изолированно, то поведение распространяется на все объекты, в нашем случаем, с требуемым нам стилем. Но самое интересное, что когда мы получаем текст с input можно уловить текст вводимый с другого inputa к классу или id которого мы цепляемся.

Реализацию самого поиска описывать пожалуй не буду. В интернете полно примеров его реализации. В данной статье хотел продемонстрировать свой подход к разделению логики элементов на странице и получения обратной связи.

Источник: https://habr.com/ru/articles/744770/


Интересные статьи

Интересные статьи

Ежемесячно мы смотрим, какие компании публикуют больше всего вакансий и изучаем активность найма в разрезе специализаций и квалификаций. А ещё собираем эффективные вакансии за месяц: те, которые привл...
Module Federation — это подход, при котором можно разделить приложение на небольшие отдельные модули и в рантайме объединять в единое приложение. Это одно из немногих рабочих решений для разработки ми...
Предлагаем вашему вниманию подборку с ссылками на новые материалы из области фронтенда и около него.
Что должен уметь фронтенд-разработчик в известной компании, которая предлагает своим покупателям широкий спектр товаров: от спортивного инвентаря и специализированной одежды до мячиков-ан...
Предлагаем вашему вниманию подборку с ссылками на новые материалы из области фронтенда и около него.