JavaScript компоненты - Введение

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

Компоненты являются автономными независимыми частями приложения, которые отвечают за обработку только одной задачи и никак не влияют на работу друг друга. У нас уже есть нативные компоненты HTML, такие как инпуты, формы, селекторы, поля, таблицы, изображения и.т.д, но как же добавлять свои собственные, которые будут так-же просто работать?

Текущее ситуация с веб-компонентами

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

На данный момент существует множество UI библиотек и фреймворков, колличество которых увеличивается почти каждую неделю. Самые популярные из них это React JS и VUE. Одна из главных проблем связанных с этими библиотеками, это маркетинговый хайп и огромный размер бандла и слишком большая сложность. 

Самый мощный фреймворк JavaScript - это сам JavaScript.

Нужны ли нам дополнительные инструменты? Новый язык / синтаксис, новые излишние уровни абстракции? Повышенный расход ресурсов и время для обработки подобных задач? JavaScript был разработан всего за 10 дней, чтобы его могли использовать простые люди, например дизайнеры, что бы просто реализовывать свои идеи. Независимо от того, что вы уже изучили сегодня — JavaScript по-прежнему является самым мощным, простым и гибким способом решать возложенные на него задачи, и вам не нужна целая инфраструктура для создания современного приложения на JS. Да, веб-тенденции эволюционируют десятимильными в последнее время, и JavaScript следует в ногу с ними.

Как же в таком случае создать простой JavaScript компонент?

Одна из самых мощных функций языка JavaScript которой нет ни в одном другом языке это Объектная Литеральная нотация, а так-же простота и гибкость в создании и изменении объектов. Давайте просто использует это. Вот так просто мы можем создать компонент:

const Button = {
  tagName: 'btn',
  init(btn) {
    btn.addEventListener('click', () => {
      btn.textContent++;
    });
  },

  getAll(container = document.body) {
    return container.getElementsByTagName(this.tagName);
  }
};

Как видите, это просто элементарный объект JavaScript. Более того, недавно я нашел шаблон Object-Speaking pattern без конструктора New и прототипы с использованием идеи, лежащей в основе шаблона factory pattern, простейшегоспособа создания объектов в JavaScript. Почти каждый метод будет получать DOM элемент в качестве первого аргумента. У вас есть только один глобальный объект Button, который срабатывает на всех кнопках в DOM'е, это и есть ваш компонент. Вывам не нужно создавать нкаких новых экземпляров и вы всегда можете получить доступ к любой кнопке из любой части вашего кода без использования шаблона Singleton pattern.

Как реализовывались компоненты JavaScript за многие годы до начала войн современных фреймворков?

Более 10 лет компоненты на чистом JS разрабатывались как плагины для jQuery или автономные виджеты. Проще говоря, это были те самые, простые объекты и функции в JavaScript. В большинстве случаев вы импортировали один файл и просто вызвали метод init(). Когда компонент был бы вставлен в DOM после загрузки кода, как простой выпадающий список, вам приходилось бы вручную вызвать метод init() на новом элементе DOM. 

Тем не менее, были доступны события DOM, которые мы могли бы использовать для прослушивания изменений в DOM, таких как добавленный, удаленный или измененный новый тег. Таким образом мы могли бы использовать их для вызова init() или deinit() автоматически. Проблема была в производительности, и из-за этого сегодня у нас есть современный API Mutation Observer, который работает во всех современных браузерах включая IE11. 

Вы можете инициализировать только один MutationObserver и прослушивать изменения во всем document.body, а затем регистрировать собственные калбеки, когда, например, новый тег добавляеться в DOM. Поскольку API-интерфейс Mutation Observer и даный алгоритм требуют логической реализации, каждый раз, когда я создаю DOM Observer, который можно легко использовать для работы с подобными задачами, просто вызовите DOMObserver.onInsert('tagname', callback).