Организация циклов в Alpine.js
03-12-2020Время чтения ~ 4 мин.Alpine.js 6297
Циклы используются там, где нужно повторить какой-то html-вывод по единому шаблону. Я уже показывал пример использования при выводе данных, полученных по Ajax.
То есть первый вид цикла — это обход готового массива данных. Второй вариант — это цикл с заданным количеством итераций.
В Alpine.js для организации циклов используется директива x-for
. Как и x-if
она может применяться только к тэгу TEMPLATE и иметь один корневой элемент.
Заданное количество итераций
В обычной практики такие задачи достаточно редки, поэтому я придумал пример по выводу css-класса цвета Berry CSS.
<div x-data> <div class="b-flex flex-wrap"> <template x-for="i in 9"> <div :class="'bg-blue'+ i + '00'" :title="'blue' + i + '00'" class="pad20"></div> </template> </div> </div>
Это достаточно простой пример, где в цикле используется переменная i
— счётчик. Мы её используем, чтобы сформировать имя класса и всплывающую подсказку.
Обычно такие циклы делаются на JS или PHP, а тут вся магия на уровне HTML.
Этот пример можно усложнить.
<div x-data> <div class="b-flex flex-wrap"> <template x-for="i in 9"> <div :class="{ 'bg-blue100 t-blue500': i == 1, 'bg-blue200 t-blue600': i == 2, 'bg-blue300 t-blue700': i == 3, 'bg-blue400 t-blue800': i == 4, 'bg-blue500 t-white': i == 5, 'bg-blue600 t-blue50': i == 6, 'bg-blue700 t-blue100': i == 7, 'bg-blue800 t-blue200': i == 8, 'bg-blue900 t-blue300': i == 9, }" x-text="'blue' + i + '00'" class="pad10 t90"></div> </template> </div> </div>
Смысл тот же, только больше логики для каждой итерации.
Обратите внимание, что данный цикл начинается с единицы, а не с нуля.
Обход данных в цикле
Суть такого цикла в том, чтобы отделить данные от их представления. Например табличный вывод однотипных данных, где удобней задать данные каждой строки в виде массива, а вывод уже сделать по шаблону.
Например такой вариант.
<div x-data='{users: [ {id: 1, name: "Leanne Graham", email: "Sincere@april.biz"}, {id: 2, name: "Ervin Howell", email: "Shanna@melissa.tv"}, {id: 3, name: "Clementine Bauch", email: "Nathan@yesenia.net"} ]}'> <template x-for="user in users" :key="user.id"> <div class="b-flex"> <div x-text="user.name" class="w3col"></div> <div x-text="user.email"></div> </div> </template> </div>
Здесь в переменной users
хранится массив данных по каждому пользователю. Ключ :key
для цикла может не использоваться, но рекомендуется для улучшения работы Alpine.
При желании данные можно разместить в отдельной функции и подключить её в x-data
.
Преобразование PHP-массива в JSON для JS
Намного интереснее вариант, когда данные получаются через PHP. Это может быть запрос к базе данных, а может и файл, который возвращает результат по return
. В любом случае эти данные нужно как-то преобразовать в JS-код, а точнее в JSON-формат.
На самом деле — это просто, поскольку в PHP уже есть готовая функция json_encode()
.
<?php $users = [ [ 'id' => 1, 'name' => 'Leanne Graham', 'email' => 'Sincere@april.biz', ], [ 'id' => 2, 'name' => 'Ervin Howell', 'email' => 'Shanna@melissa.tv', ], [ 'id' => 3, 'name' => 'Clementine Bauch', 'email' => 'Nathan@yesenia.net', ], ]; $jsonData = json_encode($users, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK); ?> <div x-data='{users: <?= $jsonData ?>}'> <template x-for="user in users" :key="user.id"> <div class="b-flex"> <div x-text="user.name" class="w3col"></div> <div x-text="user.email"></div> </div> </template> </div>
Нюанс в том, что функцию json_encode()
нужно использовать с параметрами JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK
. Тогда она вернёт нормальные данные для JavaScript.
Доступ к счетчику текущей итерации цикла
Обратите внимание, что в данных есть уникальный id — это вроде как «номер по списку». Во многих случаях он не нужен, поскольку данные можно нумеровать последовательно с первого по последний. Для таких случаев предусмотрен дополнительный синтаксис x-for
.
<div x-data='{users: [ {name: "Leanne Graham", email: "Sincere@april.biz"}, {name: "Ervin Howell", email: "Shanna@melissa.tv"}, {name: "Clementine Bauch", email: "Nathan@yesenia.net"} ]}'> <template x-for="(user, index) in users" :key="user.name"> <div class="b-flex"> <div x-text="index + 1 + '.'" class="mar5-r"></div> <div x-text="user.name" class="w3col"></div> <div x-text="user.email"></div> </div> </template> </div>
В данных я убрал поле id
, а в цикле добавил переменную для счетчика index
. В шаблоне мы просто его выводим как и другие переменные.
Нумерация такого счетчика с нуля, поэтому я прибавляю 1 и добавляю точку для красоты.
Также счётчики можно вкладывать друг в друга. Это нужно, когда данные представляют собой многомерный массив массивов, но я уже с трудом представлю себе такие задачи на практике. :-)