• Час читання ~3 хв
  • 18.03.2023

Alpine.js - це новий легкий фреймворк JavaScript, який використовує підхід додавання поведінки безпосередньо у вашій HTML-розмітці. Згідно з документацією;

Alpine.js пропонує вам реактивний і декларативний характер великих фреймворків, таких як Vue або React, за набагато нижчою вартістю. Ви можете зберегти свій DOM і посипати поведінку так, як вважаєте за потрібне.

Після включення коду – я використовую метод npm – ви можете посипати потрібну поведінку. Вони забезпечують акуратність приклад для вкладок;

<div x-data="{ tab: 'foo' }">
    <button class="button" :class="{ 'button--active': tab === 'foo' }" x-on:click="tab = 'foo'">Foo</button>
    <button class="button" :class="{ 'button--active': tab === 'bar' }" x-on:click="tab = 'bar'">Bar</button>

    <div x-show="tab === 'foo'">Tab Foo</div>
    <div x-show="tab === 'bar'">Tab Bar</div>
</div>

Якщо ви розумієте базові HTML та JavaScript, ви, сподіваємось, можете зрозуміти, що відбувається досить легко. Події кліків додаються до <button> елементів за допомогою атрибутаx-on:click. Атрибут x-show - це обчислення, який елемент показати. І :class використовується для додавання «активного» класу до кнопки.

Набір елементів стає компонентом за допомогою атрибутаx-data, який у прикладі вище за замовчуванням використовує видиму вкладку.

Створення списку

перетягування, яке мені нещодавно знадобилося для створення інтерфейсу перетягування. Зазвичай я тягнувся б до попередньо створеного рішення, дослідження які пакети доступні і вирішують, що використовувати. Це було зроблено для того, щоб уникнути кросбраузерних проблем і заново винайти колесо.

Однак підтримка JavaScript значно покращилася з роками, і браузери додали Вбудована підтримка подій перетягування. Це відносно невелика складова, тому не мало особливого сенсу використовувати велику бібліотеку для досягнення того, що було потрібно.

Його створення

Першим кроком у створенні будь-якого подібного компонента є визначення HTML, який ми хочемо використовувати. Я використовував методологію BEM, щоб допомогти угоді про іменування.

Нам знадобляться два списки, кожен зі своїм заголовком, контейнером і дільником.

<div class="drag-and-drop">
    <div class="drag-and-drop__container drag-and-drop__container--from">
        <h3 class="drag-and-drop__title">From</h3>
        <ul class="drag-and-drop__items">
            
            <li class="drag-and-drop__item"></li>
            
        </ul>
    </div>
    <div class="drag-and-drop__divider">⇄</div>
    <div class="drag-and-drop__container drag-and-drop__container--to">
        <h3 class="drag-and-drop__title">To</h3>
        <ul class="drag-and-drop__items">
            
            <li class="drag-and-drop__item"></li>
            
        </ul>
    </div>
</div>

Створіть альпійський.js компонент

Тепер нам потрібно почати додавати наш Alpine.js. Почніть з додавання атрибута, x-data щоб налаштувати нашу нову область компонентів.

<div class="drag-and-drop" x-data>
    ...
</div>

Далі нам потрібно позначити, які елементи можна перетягувати. Ми хочемо, щоб його <li> можна було перетягнути, тому додаємо до нього атрибут.

<li class="drag-and-drop__item" draggable="true"></li>

Прив'язка подій

Нам потрібно визначити, куди можна скинути перетягується елемент. Нам потрібно прив'язати подію до обох <ul> елементів. Тут ми можемо використовувати атрибут Alpine.jsx-on.

<ul class="drag-and-drop__items" x-on:drop="">
    ...
</ul>

Є й інші події, які ми можемо слухати, щоб додати доступності до взаємодії з користувачем.

<ul class="drag-and-drop__items"
  x-on:drop=""
  x-on:dragover.prevent=""
  x-on:dragleave.prevent="">
  ...
</ul>

Налаштування даних і перемикання

На даний момент це лише оболонки подій і насправді нічого не роблять. Щоб зробити їх корисними, ми можемо почати маніпулювати дані про компонент. Для початку нам потрібно налаштувати, про які властивості компонента повинен піклуватися. Ми хочемо знати коли елемент додається або видаляється. Ми можемо налаштувати ці за замовчуванням так;

<div class="drag-and-drop" x-data="{ adding: false, removing: false }">
    ...
</div>

Тепер ми можемо маніпулювати цими атрибутами всередині наших подій. Для нашого списку "Кому" ми хочемо знати Коли ми додаємо новий елемент, ми оновлюємо adding властивість. Аналогічно, ми б оновили removing нерухомість за списком "Від". Ось як зараз виглядає список "Кому".

<ul class="drag-and-drop__items"
  x-on:drop=""
  x-on:dragover.prevent="adding = true"
  x-on:dragleave.prevent="adding = false">
  ...
</ul>

Ми змінили деякі значення, але немає видимих відгуків інтерфейсу користувача, коли це відбувається. Ми можемо зробити це, змінивши стилі, шляхом зміни класів у списку. Коли властивість adding true є, ми можемо додати a новий клас з використанням :class атрибута. Цей клас видаляється, коли властивість adding є false.

<ul class="drag-and-drop__items"
  :class="{ 'drag-and-drop__items--adding': adding }"
  x-on:drop=""
  x-on:dragover.prevent="adding = true"
  x-on:dragleave.prevent="adding = false">
  ...
</ul>

Ми будемо використовувати той самий синтаксис при видаленні елементів, перемикаючи властивість removing і змінюючи клас. Я використовував класdrag-and-drop__items--removing, але ми могли б використовувати однакову назву класу для обох списків.

Ми можемо застосувати ту саму ідею до стилізації предмета, який ми хочемо перетягнути. На даний момент у нас є тільки draggable застосований атрибут. Давайте встановимо кожен елемент як компонент, зв'яжемо деякі події та оновимо клас.

<li
  class="drag-and-drop__item"
  :class="{ 'drag-and-drop__item--dragging': dragging }"
  draggable="true"
  x-data="{ dragging: false }"
  x-on:dragstart.self="dragging = true"
  x-on:dragend="dragging = false">
  ...
</li>

Зверніть увагу, .self що ми додали модифікатор до прив'язки події. У документації сказано;

Додавання .self до слухача події запустить обробника лише в тому випадку, якщо це $event.target сам елемент.

Обробляйте перетягування

Поки що ми зв'язали кілька подій і використали ці події, щоб забезпечити доступність користувальницького інтерфейсу, оновивши перетягування стилю елемента та показ місця, куди елемент може бути скинутий. Далі нам потрібно фактично перемістити елемент.

Нам потрібно використовувати dragstart подію для оновлення об'єктаdataTransfer. Цей об'єкт зберігає інформацію який доступний для проведення drop заходу. Коли ми рухаємо наш предмет, ми встановлюємо effectAllowed власність на move. По-друге, нам потрібно додати інформацію про нашу стихію до заходу. Оскільки кожен предмет має , idми можемо використовувати що як орієнтир.

x-on:dragstart.self="
  dragging = true;
  event.dataTransfer.effectAllowed = 'move';
  event.dataTransfer.setData('text/plain', event.target.id);
"

Тепер подія, яку ми прив'язали до цільового контейнера, drop має доступ до цієї інформації. Замість того, щоб використовувати setData() метод, можна використовувати getData() метод з dataTransfer об'єкта. Це поверне id пункт, який ми скидаємо. Ми хочемо додати наш елемент до цілі. Використовуючи стандартний JavaScript, ми можемо це зробити;

x-on:drop.prevent="
  const id = event.dataTransfer.getData('text/plain');
  const target = event.target.closest('ul');
  const element = document.getElementById(id);
  target.appendChild(element);
"

Код

Тепер у нас є всі окремі частини для побудови компонента перетягування. Складаючи все це воєдино, це повинно виглядати так;

<div class="drag-and-drop" x-data="{ adding: false, removing: false }">
    <div class="drag-and-drop__container drag-and-drop__container--from">
        <h3 class="drag-and-drop__title">From</h3>
        <ul
            class="drag-and-drop__items"
            :class="{ 'drag-and-drop__items--removing': removing }"
            x-on:drop="removing = false"
            x-on:drop.prevent="
                const id = event.dataTransfer.getData('text/plain');
                const target = event.target.closest('ul');
                const element = document.getElementById(id);
                target.appendChild(element);
            "
            x-on:dragover.prevent="removing = true"
            x-on:dragleave.prevent="removing = false">
            
            <li
                id="item-1"
                class="drag-and-drop__item"
                :class="{ 'drag-and-drop__item--dragging': dragging }"
                x-on:dragstart.self="
                    dragging = true;
                    event.dataTransfer.effectAllowed = 'move';
                    event.dataTransfer.setData('text/plain', event.target.id);
                "
                x-on:dragend="dragging = false"
                x-data="{ dragging: false }"
                draggable="true">
                Your Item #1
            </li>
        </ul>
    </div>
    <div class="drag-and-drop__divider">⇄</div>
    <div class="drag-and-drop__container drag-and-drop__container--to">
        <h3 class="drag-and-drop__title">To</h3>
        <ul
            class="drag-and-drop__items"
            :class="{ 'drag-and-drop__items--adding': adding }"
            x-on:drop="adding = false"
            x-on:drop.prevent="
                const id = event.dataTransfer.getData('text/plain');
                const target = event.target.closest('ul');
                const element = document.getElementById(id);
                target.appendChild(element);
            "
            x-on:dragover.prevent="adding = true"
            x-on:dragleave.prevent="adding = false">
            
        </ul>
    </div>
</div>

Резюме

Сподіваюся, ви знайшли цей підручник корисним, особливо якщо ви новачок у світі Alpine.js.

Це дуже проста реалізація перетягування з мінімальним JavaScript завдяки Alpine.js. Він все ще потребує вдосконалення, наприклад, для підтримки повторного замовлення в кожному списку. Але це відчувається як хороша відправна точка.

Особисто я б зараз почав переміщати JavaScript в окремий файл. Я б зберіг прив'язку до події і перемикання класів в HTML, але довші блоки JavaScript були б більш підтримуваними в конкретному файлі JavaScript.

Попередній перегляд

Ви можете переглянути цей код у дії на демонстрації Codepen.


Детальніше ...

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297