О web-разработке
и даже немного больше...

Ajax-загрузка записей при скроллинге и нажатии кнопки

На сегодняшний день уже стало вполне привычным наблюдать большое количество записей на страницах вывода различного рода контента, начиная от комментариев в новостных сайтах, заканчивая популярными социальными сетями. Для комфортного восприятия контента довольно часто разработчики приходят к довольно интересному приёму, который с каждым разом всё больше приходит на смену традиционной постраничной навигации.

Работает это таким образом, изначально на странице подгружается определенное количество записей, после чего на страницы посредством Ajax могут быть подгружены другие записи, загрузка которых может стартовать в момент скроллинга до самого низа страницы, либо по нажатию кнопки «далее».

Как сделать подобное в своих проектах мы рассмотрим далее. Мы попробуем сделать два варианта реализации. Первый – контент будет подгружается в момент, когда при скроллинге пользователь достигает конца страницы. Второй вариант – контент будет подгружаться при нажатии кнопки далее. Оба эти метода довольно часто используются.

Первым делом для наших примеров нужно создать базу данных, назовём её по-простому: test, в кодировке utf-8. После это так же создадим таблицу, в которой и будут хранится записи. Структура так же проста, и показана на скриншоте:

В ней предварительно я добавил некоторое количество записей, с которыми нам предстоит работать. В вашем случае это могут быть какие-либо комментарии, либо записи новостной ленты.

Для наглядности записей я добавил порядка 30 штук, т.к. подгружать мы их будет по 10 за одну загрузку. Такое количество выбрано для примера, вы можете изменить его на своё усмотрение.

После того как база подготовлена, мы приступаем к коду. Первое что нам потребуется, это подключение к базе данных MySQL. Для этого создадим файл с именем db.php, в котором следует прописать код ниже:

<?php

// параметры подключения к бд
$db_host = "localhost";
$db_name = "test";
$db_user = "root";
$db_pass = "";

// соединение с бд
$db = mysqli_connect ($db_host, $db_user, $db_pass, $db_name) or die ("Невозможно подключиться к БД");
mysqli_query ($db, 'set character_set_results = "utf8"'); // задаем кодировку данных

?>

Настройки подключения к базе вы указываете свои. Чтобы не дублировать код, эту программную часть мы вывели в отдельный файл, который в дальнейшем будет подключаться в начале наших
скриптов.

После этого, создадим скрипт с именем ajax.items.php, основная задача которого будет выборка данных из базы данных, и возврат их в формате json.

<?php
include 'db.php';

$articles = array(); // массив для результата выборки записей

// простая проверка переменной
if (isset($_POST['start']) && is_numeric($_POST['start'])){

	$start = $_POST['start']; // точка старта выборки

	// получаем 10 записей начиная с точки старта
	$res = mysqli_query($db, "SELECT * FROM `posts` ORDER BY `id` DESC LIMIT {$start}, 10");
	while ($row = mysqli_fetch_assoc($res)){
		$articles[] = $row;
	}

}

// Превращаем массив статей в json-строку для передачи через Ajax-запрос
echo json_encode($articles);
?>

Итак, чтобы получить данные от скрипта посредством ajax-запроса, нам предстоит передать POST-параметр start, который будет передавать значение, с которого следует произвести выборку данных. Как вы, наверное, уже поняли, после каждой такой выборки, в самом скрипте значение start будет изменяться.

Теперь, что что касается непосредственной страницы вывода записей. Ранее мы говорили, что выводить записи вы может двумя способами, первый это путём скроллинга, второй путём специальной
кнопки. Два этих способа принципиально не сильно отличаются, и используют Ajax.

Ajax загрузка при скроллинге

Приступим к самой странице вывода записей при скроллинге. Первым делом, перед показом самой страницы необходимо сделать первичную выборку данных.

<?php

include 'db.php';

// Получаем первые 10 статей, которые будут видны изначально
$res = mysqli_query($db, "SELECT * FROM `posts` ORDER BY `id` DESC LIMIT 10");

// Формируем массив из 10 статей
$arPosts = array();
if ($res){
	while($row = mysqli_fetch_assoc($res)){
		$arPosts[] = $row;
	}	
}
?>

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

<!DOCTYPE HTML>
<html>
<head>
	<meta charset = "utf-8" />
	<title>Ajax загрузка при скроллинге</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
</head>
<body>

<h1>Ajax загрузка при скроллинге</h1>
<div style="width:25%;" id="articles">
    <?php foreach ($arPosts as $article): ?>
        <p><b><?php echo $article['title']; ?></b><br />
        <?php echo $article['text']; ?></p>
    <?php endforeach; ?>
</div>

</body>
</html>

Далее в теле разметке этой же страницы до закрывающего тега body так же добавим код на js. Его так же можно вывести в отдельный js-файл, и подгружать его на странице, мы же в целях простоты примера будем использовать его на этой же странице.

<script type="text/javascript">
$(document).ready(function(){

var inProgress = false; // статус процесса загрузки
var startFrom = 10; // позиция с которой начинается вывод данных

    $(window).scroll(function() {

        // высота окна + высота прокрутки больше или равны высоте всего документа
        if ($(window).scrollTop() + $(window).height() >= $(document).height() - 200 && !inProgress) {
			$.ajax({
				url: 'ajax.items.php', // путь к ajax-обработчику
				method: 'POST',
				data: {
					"start" : startFrom
				},
				beforeSend: function() {
					inProgress = true;
				}
			}).done(function(data){
				data = jQuery.parseJSON(data); // данные в json
				if (data.length > 0){
					// добавляем записи в блок в виде html
					$.each(data, function(index, data){
						$("#articles").append("<p><b>" + data.title + "</b><br />" + data.text + "</p>");
					});
					inProgress = false;
					startFrom += 10;
				}
			});
		}
    });
});
</script>

В итоге если после того как вы введете все эти части кода на странице, выглядеть она будет должна следующим образом:

<?php

include 'db.php';

// Получаем первые 10 статей, которые будут видны изначально
$res = mysqli_query($db, "SELECT * FROM `posts` ORDER BY `id` DESC LIMIT 10");

// Формируем массив из 10 статей
$arPosts = array();
if ($res){
	while($row = mysqli_fetch_assoc($res)){
		$arPosts[] = $row;
	}	
}
?>
<!DOCTYPE HTML>
<html>
<head>
	<meta charset = "utf-8" />
	<title>Ajax загрузка при скроллинге</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
</head>
<body>

<h1>Ajax загрузка при скроллинге</h1>
<div style="width:25%;" id="articles">
    <?php foreach ($arPosts as $article): ?>
        <p><b><?php echo $article['title']; ?></b><br />
        <?php echo $article['text']; ?></p>
    <?php endforeach; ?>
</div>

<script type="text/javascript">
$(document).ready(function(){

var inProgress = false; // статус процесса загрузки
var startFrom = 10; // позиция с которой начинается вывод данных

    $(window).scroll(function() {

        // высота окна + высота прокрутки больше или равны высоте всего документа
        if ($(window).scrollTop() + $(window).height() >= $(document).height() - 200 && !inProgress) {
			$.ajax({
				url: 'ajax.items.php', // путь к ajax-обработчику
				method: 'POST',
				data: {
					"start" : startFrom
				},
				beforeSend: function() {
					inProgress = true;
				}
			}).done(function(data){
				data = jQuery.parseJSON(data); // данные в json
				if (data.length > 0){
					// добавляем записи в блок в виде html
					$.each(data, function(index, data){
						$("#articles").append("<p><b>" + data.title + "</b><br />" + data.text + "</p>");
					});
					inProgress = false;
					startFrom += 10;
				}
			});
		}
    });
});
</script>

</body>
</html>

Логика работы данного кода проста, давайте немного повторим. При загрузке страницы первоначально будет загружено 10 записей. При скроллинге страницы к самому низу, будет срабатывать триггер, который собственно и будет посредством ajax-запрос подгружать в документ последующие 10 записей. И далее пока записи в базе есть, при скроллинге будут планомерно выводиться записи. Всё действительно просто, не так ли? Второй способ отличается незначительно, давайте теперь рассмотрим его.

Ajax-загрузка при нажатии на кнопку «далее»

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

<?php

include 'db.php';

// Получаем первые 10 статей, которые будут видны изначально
$res = mysqli_query($db, "SELECT * FROM `posts` ORDER BY `id` DESC LIMIT 10");

// Формируем массив из 10 статей
$arPosts = array();
if ($res){
	while($row = mysqli_fetch_assoc($res)){
		$arPosts[] = $row;
	}	
}
?>

По аналогии с предыдущим примером, так же в заголовке страницы подключаем JQuery, а также в самом теле документа, после вывода записей в конце у нас появляется кнопка «далее». Пожалуй, это основное отличие, если говорить о html-разметке.

<!DOCTYPE HTML>
<html>
<head>
	<meta charset = "utf-8" />
	<title>Все статьи</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
</head>
<body>
<h1>Ajax-загрузка записей посредством кнопки</h1>
<div style="width:25%;" id="articles">
    <?php foreach ($arPosts as $article): ?>
        <p><b><?php echo $article['title']; ?></b><br />
        <?php echo $article['text']; ?></p>
    <?php endforeach; ?>
</div>
<button id="more">Дальше</button>

</body>
</html>

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

<script type="text/javascript">
$(document).ready(function(){

var inProgress = false; // идет процесс загрузки
var startFrom = 10; // позиция с которой начинается вывод данных

    $('#more').click(function() {
		if (!inProgress) {
			$.ajax({
				url: 'ajax.items.php', // путь к ajax-обработчику
				method: 'POST',
				data: {
					"start" : startFrom
				},
				beforeSend: function() {
					inProgress = true;
				}
			}).done(function(data){
				data = jQuery.parseJSON(data); // данные в json
				if (data.length > 0){
					// добавляем записи в блок в виде html
					$.each(data, function(index, data){
						$("#articles").append("<p><b>" + data.title + "</b><br />" + data.text + "</p>");
					});
					inProgress = false;
					startFrom += 10;
				}
			});
		}
    });
});
</script>

По нажатии на кнопки будет происходить ajax-запрос записей, и добавляться в конец страницы. Таким образом, кнопка будет продолжать оставаться внизу, и при надобности пользователь сможет загружать новые записи по нажатию на этой кнопки. С точки зрения экономии ресурсом, данный метод является более щадящим. Т.к. не во всех случаях и скроллинга страницы есть потребности в запросе данных из базы. В целом, код страницы вывода записей по кнопке будет выглядеть таким образом.

<?php
include 'db.php';

// Получаем первые 10 статей, которые будут видны изначально
$res = mysqli_query($db, "SELECT * FROM `posts` ORDER BY `id` DESC LIMIT 10");

// Формируем массив из 10 статей
$arPosts = array();
if ($res){
	while($row = mysqli_fetch_assoc($res)){
		$arPosts[] = $row;
	}	
}
?>
<!DOCTYPE HTML>
<html>
<head>
	<meta charset = "utf-8" />
	<title>Все статьи</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
</head>
<body>
<h1>Ajax-загрузка записей посредством кнопки</h1>
<div style="width:25%;" id="articles">
    <?php foreach ($arPosts as $article): ?>
        <p><b><?php echo $article['title']; ?></b><br />
        <?php echo $article['text']; ?></p>
    <?php endforeach; ?>
</div>
<button id="more">Дальше</button>
<script type="text/javascript">
$(document).ready(function(){

var inProgress = false; // идет процесс загрузки
var startFrom = 10; // позиция с которой начинается вывод данных

    $('#more').click(function() {
		if (!inProgress) {
			$.ajax({
				url: 'ajax.items.php', // путь к ajax-обработчику
				method: 'POST',
				data: {
					"start" : startFrom
				},
				beforeSend: function() {
					inProgress = true;
				}
			}).done(function(data){
				data = jQuery.parseJSON(data); // данные в json
				if (data.length > 0){
					// добавляем записи в блок в виде html
					$.each(data, function(index, data){
						$("#articles").append("<p><b>" + data.title + "</b><br />" + data.text + "</p>");
					});
					inProgress = false;
					startFrom += 10;
				}
			});
		}
    });
});
</script>

</body>
</html>

Как вы можете заметить схожесть с предыдущим примером в коде некая есть. Отличие лишь в кнопке и триггере, который срабатывает для запроса данных. Собственно, на этом, пожалуй, всё.

DEMO: Ajax-загрузка при скроллинге, ajax-загрузка при нажатии кнопки.

Опубликован: 20.04.2019 г.

См. также:

Загрузка файлов на сервер посредством Ajax
Отложенная загрузка изображений Lazy Load
Анимация набора текста на Typed.js
Анимация отсчёта на jquery-spincrement
Mega Dropdown — Меню для мобильной версии
Отслеживаем клик вне элемента на JQuery
Stimed – задаем CSS-стили по времени
Список выбора на JQuery

Комментарии

  1. Андрей пишет:

    выдаёт такую ошибку
    SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

  2. Жека пишет:

    ну во-первых data = jQuery.parseJSON(data); чтоб этим не заниматься, можно указать тип данных dataType: 'json',
    во-вторых
    }).done(function(data){
    if (data.length > 0){
    ...
    inProgress = false;

    у в случае любой ошибки inProgress будет true. Его нужно вывести либо в complete, либо обрабатывать ошибки и в случае с done вывести из условия

  3. Сергей пишет:

    Ajax возвращает undefined при скролле страницы

Добавить комментарий для Андрей Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Комментарии
  • Загрузка...
Друзья сайта