Введение в Alpine.js: JavaScript-фреймворк для минималистов

автор vadim


Инновации в интерфейсных JavaScript-фреймворках — одно из величайших техно-культурных явлений нашего времени. Уже более 20 лет мы наблюдаем, как разворачивается длинный хвост эволюционного творчества. Каждая новая идея попадает в общий котел, вызывая улучшения как в процессе разработки программного обеспечения, так и в конечных продуктах, которые создают разработчики.

Один из фреймворков, делающих себе имя в наши дни, — это Alpine.js. Alpine — это минималистичный фреймворк, созданный, как следует из его названия, для легкой езды по пересеченной местности. Он обеспечивает большую мощность в скудной, легко осваиваемой упаковке. Эта статья познакомит вас с Alpine.js, чтобы вы могли понять, что он дает и когда он может быть вам полезен.

Минималистичный API Alpine

Как описано в документации Alpine.js, API Alpine представляет собой набор из 15 атрибутов, шести свойств и двух методов. Это очень маленький профиль API. Его минималистская цель — обеспечить реактивность в чистом формате, дополненную некоторыми окружающими тонкостями, такими как события и центральное хранилище.

Рассмотрим очень простую веб-страницу в листинге 1.

Листинг 1. Простая веб-страница, созданная с помощью Alpine.js


<html>
<head>
  <script src="https://unpkg.com/alpinejs@3.10.3/dist/cdn.min.js" defer></script>
</head>
<body>
  <div x-data="">
    <span x-text="'Text literal'"></span>
</div>
</body>
</html>

Помимо включения пакета Alpine через CDN (ознакомиться с defer здесь семантика), единственные две вещи, связанные с Alpine, — это директивы x-data и x-text.

Если вы поместите это на HTML-страницу в своей системе и просмотрите ее в браузере, вы увидите вывод сообщения «Текстовый литерал». Хотя это приложение не очень впечатляет, оно демонстрирует два интересных аспекта Alpine.

Во-первых, чтобы реактивность заработала, вы должны заключить разметку в x-data директива. Если удалить директиву, x-text не вступит в силу. По сути, x-data директива создает компонент Alpine. В этом примере x-data директива пуста. В реальном использовании у вас почти всегда есть данные; в конце концов, вы пишете компоненты, целью которых является реакция на данные.

Второе, на что следует обратить внимание в листинге 1, это то, что вы можете поместить любой действительный код JavaScript в x-text. Это относится ко всем директивам Alpine.

Элементы x-data и x-text

x-data содержимое предоставляется всем содержащимся элементам. Чтобы понять, что я имею в виду, взгляните на листинг 2.

Листинг 2. Взаимодействие x-data и x-text


<div x-data="{ message: 'When in the course of human events...' }">
  <span x-text="message"></span>
</div>

Теперь страница выведет начало Декларации независимости. Ты это видишь x-data определяет простой старый объект JavaScript с одним полем, 'message', который содержит преамбулу Декларации. x-text относится к этому полю объекта.

Реактивность в Alpine.js

Далее мы воспользуемся реактивностью, чтобы исправить ошибку в декларации. Взгляните на листинг 3.

Листинг 3. x-on:click и реактивность


<div x-data="{ pronoun: 'men' }">
  <button x-on:click="pronoun = 'people'">Fix It</button>
  <span x-text="`all ${pronoun} are created equal`"></span>
</div>

x-text директива должна быть самоочевидной сейчас. Это относится к pronoun переменная, выставленная x-data директива. Новым элементом здесь является кнопка, которая имеет x-on:click директива. Обработчик этого события щелчка заменяет старое местоимение по умолчанию гендерно-нейтральным, а реактивность заботится об обновлении ссылки в x-text.

Функции в данных

Свойства данных в Alpine — это полнофункциональные объекты JavaScript. Давайте рассмотрим другой способ обработки вышеупомянутого требования, показанный в листинге 4.

Листинг 4. Использование функций данных


<div x-data="{ 
      pronoun: 'men', 
      fixIt: function(){
        this.pronoun = 'people';
      }
    }">
    <button x-on:click="fixIt()">Fix It</button>
    <span x-text="`all ${pronoun} are created equal`"></span>
  </div>

В листинге 4 вы можете видеть, что объект данных теперь содержит fixIt метод, который вызывается обработчиком кликов.

Кроме того, обратите внимание, что иногда вы будете видеть код приложения, который вызывается из x-data директива для функции, определенной в теге script — это личное предпочтение, и она работает точно так же, как встроенная x-data:


<div x-data="myDataFunction()">...</div>
	...
	<script>
	  function myDataFunction() {
	    return {
		  foo: "bar"
		}
	  }
	</script>

Получение удаленных данных

Теперь давайте переключим передачу и подумаем о более сложном требовании. Допустим, мы хотим загрузить список американских президентов в формате JSON из внешнего API. Первое, что мы собираемся сделать, это загрузить его при загрузке страницы. Для этого мы будем использовать x-init директива, как показано в листинге 5.

Листинг 5. Предварительная загрузка данных из x-init


<div x-data="{
      presidents: []
    }" 
    x-init="(
      async () => {
        const response = await fetch('https://raw.githubusercontent.com/hitch17/sample-data/master/presidents.json');
        presidents = await response.json();
      }
    )">
    <span x-text="presidents"></span>
  </div>

Что тут происходит? Ну, во-первых, x-data директива должна быть ясной: она просто имеет presidents поле с пустым массивом. x-text в span element выводит содержимое этого поля.

x-init код немного сложнее. Во-первых, обратите внимание, что он обернут в самовыполняющуюся функцию. Это связано с тем, что Alpine ожидает функцию, а не определение функции. (Если бы вы использовали неасинхронную форму обратного вызова fetchвам не нужно было бы обертывать функцию таким образом.)

Как только мы получили список президентов от конечной точки, мы вставляем его в presidents переменная, которую Alpine представила как часть x-data объект.

Повторюсь: Alpine.js получает данные из a-data доступны для других директивных функций (таких как x-init) в том же контексте.

Итерация с Alpine.js

На данный момент наше приложение извлекает данные из удаленной конечной точки и сохраняет их в состояние. Обратите внимание, однако, что он выводит что-то вроде [Object],[Object].... Это не то, чего мы хотим. Давайте взглянем на перебор данных, как показано в листинге 6.

Листинг 6. Итерация с помощью Alpine.js


<div x-data=...>
<ul>
      <template x-for="pres in presidents">
        <li><div x-text="pres.president"></div>
          From: <span x-text="pres.took_office"></span> Until: <span x-text="pres.left_office"></span></li>
      </template>
    </ul>
</div>

Листинг 6 содержит обычный неупорядоченный список, за которым следует элемент шаблона HTML, содержащий x-for директива. Эта директива работает аналогично тому, что вы могли видеть в других реактивных фреймворках. В этом случае это позволяет нам указать коллекцию, presidentsи идентификатор, который будет предоставлен заключенной разметке, представляющей каждый экземпляр этой коллекции, в данном случае pres.

Остальная часть разметки использует pres переменная для вывода данных из объектов через x-text.

Теперь приложение выглядит примерно так, как показано на рисунке 1.

Список президентов США, созданный с помощью Alpine.js. IDG

Рисунок 1. Список президентов США.

Показать/скрыть и по клику

Теперь мы хотим настроить приложение таким образом, чтобы данные о президенте переключались щелчком по имени президента. Для начала мы изменим разметку так, как показано в листинге 7.

Листинг 7. Показать/скрыть элементы


<template x-for="pres in presidents">
        <li><div x-text="pres.president" x-on:click="pres.show = ! pres.show"></div>
          <div x-show="pres.show">
            From: <span x-text="pres.took_office"></span> Until: <span x-text="pres.left_office"></span></li>
          </div>
      </template>

Теперь в листинге 7 мы можем использовать x-show директива о div содержащий информацию о президенте. Правдивость x-show value определяет, видимо ли содержимое. В нашем случае это определяется pres.show поле. (Обратите внимание, что в реальном приложении вы можете не захотеть использовать фактические бизнес-данные для размещения переменной show/hide.)

Чтобы изменить значение pres.show мы добавляем x-on:click обработчик заголовка. Этот обработчик просто меняет истинное/ложное значение pres.show: pres.show = ! pres.show.

Добавить анимацию перехода

В Alpine есть встроенные переходы, которые можно применить к функции «показать/скрыть». В листинге 8 показано, как добавить анимацию по умолчанию.

Листинг 8. Добавление перехода для отображения/скрытия


 <div x-show="pres.show" x-transition>
    From: <span x-text="pres.took_office"></span> Until: <span x-text="pres.left_office"></span></li>
  </div>

Единственное, что изменилось, это то, что элемент, несущий x-show директива теперь также имеет x-transition директива. По умолчанию Alpine применяет разумные переходы. В этом случае переход представляет собой эффект скольжения и затухания. Вы можете широко настроить переход, в том числе применяя собственные классы CSS к различным этапам анимации. Дополнительные сведения об этой функции см. в документации по переходу Alpine.js.

Привязка к входам

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

Листинг 9. Фильтрация президентов


<div x-data="{
      filter: '',
      presidents: [],
      getPresidents: function(){
        return this.presidents.filter(pres => pres.president.includes(this.filter) )
      }
    }" 
...
    <input x-model="filter" />
...
  <ul>
      <template x-for="pres in getPresidents">

Обратите внимание, что x-data Объект теперь имеет поле «фильтр». Это двусторонне привязано к элементу ввода через x-model директива, которая указывает на «filter.”

Мы изменили шаблон x-for директива для ссылки на новый getPresidents() метод, который реализуется на x-data объект. Этот метод использует стандартный синтаксис JavaScript для фильтрации президентов на основе того, включают ли они текст в поле фильтра.

Заключение

Как и его тезка, Alpine.js — это легкий рюкзак с основным снаряжением, которое поможет вам пройти через горы. Он минимальный, но достаточный.

Фреймворк включает в себя некоторые функции более высокого уровня, в частности, центральное хранилище и систему обработки событий, а также архитектуру плагинов и экосистему.

В целом, Alpine.js удобен в работе. Если у вас есть опыт работы с другими реактивными фреймворками, Alpine должен быть вам достаточно знаком, чтобы вы могли быстро с ним разобраться. Простота объявления компонента и его данных в x-data директива попахивает гениальностью.

Вы можете задаться вопросом о межкомпонентной связи. Alpine.js избегает явного связывания между компонентами (например, без реквизита «родитель-потомок»). Вместо этого он использует среду браузера (то есть окно) в качестве шины событий через $dispatch директива. Это соответствует философии Alpine по добавлению достаточного количества функций для расширения того, что уже есть. Это работает хорошо.

Все эти элементы подвергаются испытанию по мере увеличения размера и сложности приложения. Так что это работает с любым стеком, который вы выберете. Alpine.js — заманчивый вариант, когда вы в следующий раз начнете писать код.

Related Posts

Оставить комментарий