Alpine.js — легковесный фреймворк с удобным синтаксисом

Многие разработчики полюбили лаконичный синтаксис и мощь директив Vue.js настолько, что даже пытаются использовать этот фреймворк не только в одностраничных приложениях. Сложно отказаться от использования реактивности, только потому, что вдруг понадобилось написать небольшой проект. Не возвращаться же к старому доброму jQuery или к чистому JS?!


Надо сказать, что во Vue.js (да и во многих других фреймворках) предусмотрен такой вариант его использования. Но все же он кажется слишком громоздким для такой простой работы, а функционал избыточным. И тут на помощь приходит Alpine.js.


Отметим некоторые особенности данного фреймворка:


  1. Он весит очень мало! 7.2kB в сжатом виде.
  2. Знакомый и простой синтаксис основанный на директивах.
  3. Не использует виртуальный DOM
  4. Подключения возможно как через CDN (по задумке авторов должно быть основным использованием), так и через npm.

Рассмотрим простейший пример использования этого фреймворка:


Базовый пример


    <div x-data="{ msg: 'Hello, Habr!' }">
        <input type="text" x-model="msg" />
        <p x-text="msg"></p>
    </div>

Посмотреть весь код статьи на playcode.io


Первое, что бросается в глаза, это атрибут x-data. Это директива нашего фреймворка, она принимает JSON-объект и обеспечивает его свойствам двунаправленную реактивность. Но главная его функция это инициировать новый компонент. Обязательно нужно добавлять его в родительский Dom-узел, даже если и не собираетесь приписывать ему реактивные переменные.
В последнем случае просто добавьте



x-data="{}"

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


Теперь мы вольны использовать реактивную переменную msg, как нам угодно. Например, связываем значение переменной с текстовым <input/> с помощью директивы x-model. Опытные разработчики уже узнали в ней близняшку v-model из Vue.js. Очень полезная аналогия, поскольку использование их обеих абсолютно идентично! Повесив директиву с переменной msg, мы автоматически получаем строку 'Hello, Habr!' в поле ввода. Теперь мы можем изменять её значение, а результат увидим в следующей строке.


Тут мы вынуждены разочаровать многих, привыкших к синтаксису Vue.js и простой передаче значений переменных тэгам с помощью фигурных скобок, например, так

<p>{{ msg }}</p>

В Alpine.js этот код не сработает. Текст для тэга

придется передавать с помощью специального атрибута x-text. Для передачи целого блока разметки предусмотрен атрибут x-html.



Подписка на события


Код примера:

    <div x-data="{ counter: 1 }">
      <h1 x-text="counter"></h1>
      <button x-on:click="counter++">+1</button>
    </div>

Для подписки на события используется специальная директива x-on. Кстати все директивы в Alpine.js способны принимать не только конечное значение, но и js-выражения, этим мы и воспользовались для реализации счетчика в примере выше. Существует, и очень рекомендуется к использованию, укороченная версия x-on — @. С ней подписка на события выглядит вот так:

<button @click="counter++">+1</button>

Условный рендеринг


Следующий пример демонстрирует использование x-if:



    <div x-data="{ show: false }">
      <button
        x-on:click="show = ! show"
        x-text="show ? 'Скрыть' : 'Показать'"
      ></button>
      <template x-if="show">
        <p>Меня видно!</p>
      </template>
    </div>

Использование директивы x-if, так же не должно вызывать затруднения у фанатов Vue.js. Она принимает Boolean значение и в зависимости от этого рендерит элемент. Единственное отличие этот атрибут обязан применяться только на тэге template. Обратите внимание как используя тернарный оператор мы изменяем текст на кнопке в зависимости от ситуации.



Циклы


<div x-data="{ items: ['habr', 'hubr', 'hobr'] }">
   <ol>
     <template x-for="item in items" x-bind:key="item">
       <li>
         <p x-text="item"></p>
       </li>
     </template>
  </ol>
</div>

Директива x-for принимает массив элементов, которые мы хотим отобразить. Но сначала мы вводим новую переменную, которая будет содержать элемент массива в каждом цикле, в данном случае item. Внутри цикла мы показываем, как мы хотим отобразить каждый элемент, передаем значение item в параграф, и Alpine самостоятельно рендерит весь список. Желательно(но не обязательно) передавать уникальное значение для ключа key. Обратите внимание как мы привязываем динамическую передачу данных к атрибуту key с помощью новой директивы x-bind. x-for так же как и x-if должен располагаться в тэге template, иначе он не будет работать.



Мы попытались охватить основные примеры использования этого фреймворка. Для полного ознакомления рекомендуется посетить страницу на github.

Вторая статья о Alpine.js.

Надеемся, что вам понравилось.

Удачных проектов и до встречи!



Ну и на закуску список вкусностей, которые создатели Alpine обещают добавить в следующей версии:


  • Пользовательские директивы
  • Компоненты
  • Поддержка style атрибута
  • И многое другое...
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 21

    0
    Интересно, спасибо. Надо познакомится.
      +1
      До чего странно после Реакта воспринимается синтаксис, когда логика пишется в строковых кавычках. Упорно читаю это как string присвоение.
        0

        Alpine.js классный для небольших проектов, особенно в связке с TailwindCSS. Спасибо за статью :)

          0
          А валидация в данном случае я так понимаю посылается куда подальше?
            0
            С валидацией нет никаких проблем. Через директивы можно передавать целые методы, в том числе и для валидации.
              0

              Видимо, речь про валидный html.

                0
                Я имел в виду html
                  0
                  Тогда Вы правы
              +9
              Миллениалы изобрели первый Ангуляр.
                0

                Насколько я понял, в Alpine отслеживаются мутации модели (с observable-membrane под капотом).
                В то время как в первом ангуляре честный dirty check, который был постоянным источником проблем с производительностю.


                Больше напоминает Knockout, который как раз отслеживал мутации.

                  +2
                  Ну а что поделать, если хочется минимализма. Не брать же ради него сам первый Ангуляр)
                    0
                    Почему? (не ангуляржс обязательно, но любую подходящую технологию)
                      0
                      В случае с первым Ангуляром всё просто — именно древняя первая версия давно устарела. Куда логичнее взять столь же простую технологию, но которая активно обновляется и обещает остаться такой же минималистичной. Это именно если минимализм нужен. Про другие подходящие технологии ясное дело, что можно взять любую.
                        0
                        Почему может быть важно сферическое обновление в вакууме? Популярная старая технология уже оттестирована до предела же, бест-пратисы и рецепты сложились.
                  +7

                  Перед сравнением с другими штуками типа вью и реакта — и замечаниями что нет того, того и того — нужно учесть, что Альпайн сам по себе это присказка, а не сказка.


                  Он — часть Laravel Livewire, который дает возможность писать реактивный фронтэнд прямо из… контроллеров бэкенда. То есть сразу получая удобный доступ ко всей валидации, моделям и другим мощностям ларавеля без необходимости настройки общения фронта и бэка.


                  https://laravel-livewire.com/

                    0
                    Спасибо за информацию!
                      0
                      А такое счастье есть для Symfony?
                        +1
                        Прям такого к сожалению, вроде нет, потому что Livewire очень чётко заточен под Ларавель и его шаблонизатор.

                        Но можно поглядеть на Inertia, примерно такой же смысл:
                        inertiajs.com
                      +2

                      Если я не ошибаюсь, то по сути это лайт Vue.js… и это классно. Действительно, когда пишешь какой-нибудь не очень сложный проект на одну страницу по типу Hello World, то юзать Vue становится не целесообразным. Пойду ознакомлюсь подробнее.

                        0
                        Единственное отличие этот атрибут обязан применяться только на тэге template.
                        x-for так же как и x-if должен располагаться на template, иначе он не будет работать.
                        Из статьи пропали упоминания про тег template. А именно про то, что x-if и x-for могут использоваться только в теге template.
                          0
                          Спасибо, поправил.

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

                        Самое читаемое