Сайт вебмастера

Организация циклов в 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 и добавляю точку для красоты.

Также счётчики можно вкладывать друг в друга. Это нужно, когда данные представляют собой многомерный массив массивов, но я уже с трудом представлю себе такие задачи на практике. :-)

Похожие записи