Как создать веб-сайт с помощью AJAX - Блог ITVDN
ITVDN: курсы программирования
Видеокурсы по
программированию

    Выбери свою IT специальность

    Начать бесплатно

    Выбери свою IT специальность

    Начать бесплатно

      Как создать веб-сайт с помощью AJAX

      Создания простого чата

      Для начала создадим простой чат с помощью HTML&CSS и PHP&MySQL

      Проектирование Базы Данных

      1. Переходим к phpMyAdmin.
      2. Создаем новую базу данных, называем “chatdb”.
      3. Создаем новую таблицу, называя “Posts”, включая в себя 4 столбца:
      • “id” тип колонки INT, автоматическое увеличение на 1 (задаем A_I в ячейку с флажком) основной ключ (index);
      • “nick” тип колонки VARCHAR и длина 100;
      • “post_text” тип колонки TEXT;
      • “post_dt” тип колонки DATETIME по умолчанию является CURRENT_TIMESTAMP.

      Создание веб-сайта.

      1. Во-первых, создадим главную страницу. Список комментариев и отправка формы, используя кнопку. Всё будет находится в файле “index.php” .  Давайте создадим этот файл и напишем что-то вроде этого: 

      <html>

      <head>

      head>

      <body>

      php

      $mysqli = new mysqli("127.0.0.1", "root", "", "chatdb");

      /* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */

      /* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */

      /* "chatdb" is DB's name. */

      /* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */

      $result = $mysqli->query("SELECT * FROM posts;");

      ?>

      <style>

      /* All CSS is very simplified. I provide it for example and no more.

       * In Chrome it works tolerably, but in IE and Firefox it works very poorly.

       */

      .content {

        display: table;

        width: 50%;

        min-width: 400px;

        height: 80%;

        /* Center horizontally and vertically */

        position: absolute;

        left: 0; right: 0;

        top: 0; bottom: 0;

        margin: auto;

        /* Design */

        border: 1px solid;

        background-color: silver;

        padding: 5px;

      }

      /* For mobile devices */

      @media (max-width: 400px) {

        .content {

          width: 100%;

          min-width: 0;

          padding: 0px;

        }

      }

      style>

      <div class="content">

      <div id="comments" style="overflow-y: scroll; height: 100%;">

      php

      if ($result) {

        while ($post = $result->fetch_object()){

          $nick = $post->nick;

          $post_dt = $post->post_dt;

          $post_text = $post->post_text;

         

          echo "<b>$nickb> ($post_dt):<br>";

          echo "$post_text<br>";

          echo "<br>";

        }

        $result->close();

      }

      ?>

      div>

      php

      $mysqli->close();

      ?>

      <form action="post.php" method="post" style="height: 0; display: table-row;">

        Nick:<br>

        <input type="text" name="nick" style="width: 100%;">input><br>

        <br>

        Text:<br>

        <textarea name="text" style="width: 100%;">textarea><br>

        <br>

        <input type="submit">input>

      form>

      div>

      <script type="text/javascript">

          var divComments = document.getElementById('comments');

          divComments.scrollTop = divComments.scrollHeight;

      script>

      body>

      html>

      2. Дальше давайте создадим “post.php” файл и напишем такое: 

      php

      $nick = $_POST['nick'];

      $post_text = $_POST['text'];

      $mysqli = new mysqli("127.0.0.1", "root", "", "chatdb");

      $nick = $mysqli->real_escape_string($nick);

      $nick = htmlspecialchars($nick);

      $post_text = $mysqli->real_escape_string($post_text);

      $post_text = htmlspecialchars($post_text);

      $mysqli->query("INSERT INTO posts (nick, post_text) VALUES ('$nick', '$post_text');");

      $mysqli->close();

      /* Redirect To Main Page */

      header('Location: ' . $_SERVER['HTTP_REFERER']);

      ?>

      3. Откроем ваш чат в любом продвинутом браузере. Вся работа: 

      4. Напишите ник и текст, а потом нажмите на кнопку отправки. 

      Когда отправили форму, сразу же происходит перенаправление формы главной страницы в “post.php”. “Post.php” моментально наполняет данными таблицу и перенаправляет на главную страницу. Также “post.php” содержит начальный XSS и SQL защищенный вход. Для упрощения не отправляем клиентам время с JS на “post_dt” на внесения данных, а указываем значение по умолчанию – CURRENT_TIMESTAMP, который предоставляет нынешнюю дату и время на сервер.

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

      Что тут не так?

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

      Это очень, очень серьезная проблема для любого чата.

      Как это исправить?

      Очевидно, один из путей сделать это - использовать HTTP-запрос к фоновой работе автоматически (с помощью JS) и асинхронно, то есть это один из способов обеспечить выполнение AJAX в любой form.

      Проблема номер 2. Также неправильно то, что кнопка отправки перезагружает страницу (перенаправляет на вторую страницу и следующим шагом возвращает назад).

      При перезагрузке страницы сбрасывает “Nick” в  поле (также, как любые другие изменения, те, что сделали с пользователем)

      Как это исправить?

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

      Проблема номер 2.1. Видите ли что-то необычное тут?

      Это слишком быстро?

      Дело с чатом очень простое – загружаем только два маленьких текстовых параметра. Что делать, если нужно улучшить чат с помощью добавления присоединения, а конкретно - изображений и видео? Видео может иметь объем в размере нескольких мегабайт, что тогда в этом случае?

      Давайте попробуем.  Давайте немного изменим “post.php”, после $mysql->query() добавив это: 

      for ($i = 0; $i < 1000000000; $i++) { }

      Старайтесь размещать какие-либо комментарии. Что мы видим? Нет, UI не остановилось (заморозилось), но браузер ждет до того, как закончится подключение:  

      Да, если “post.php” вызывает какую-то необработанную ошибку, то чат исчезает, и пользователь видит пустое окно с сообщением о непонятной ошибке. Чтобы вернуться к чату, пользователю стоит нажать кнопку “Back” в браузере. И это проблема номер 2.2.

      Давайте уберем петлю с “post.php” и исправим эти проблемы.

      Реализация легкого AJAX в простой чат

      Автоматическое обновление комментариев

      Эта веб-страница без AJAX? Это веб-страница, которая полностью перезагружается.

      Эта веб-страница c AJAX? Это веб-страница, что перезагружается частично.

      Где же взять части этих страниц? Стоит разделить нашу страницу на части, в этом случае сервер генерирует страницу частично.

      Страница будет состоять из двух частей – блок комментариев и другой контент страницы. Комментарии будут загружаться и перезагружаться отдельно от другой страницы.

      Давайте сделаем первую часть, то есть блок комментариев.

      Для начала создадим пустой файл, назовем “getcomment.php”.

      Дальше переходим в “index.php” для того, чтобы вырезать комментарии и далее отделить его.
      1. Вырезаем инициализированный блок MySQL с “index.php" 

      php

      $mysqli = new mysqli("127.0.0.1", "root", "", "chatdb");

      /* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */

      /* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */

      /* "chatdb" is DB's name. */

      /* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */

      $result = $mysqli->query("SELECT * FROM posts;");

      ?>

      вставляем в “getcomments.php”.

      2. Следующее, вырежем контент div c комментариями с “index.php”:

      php

      if ($result) {

        while ($post = $result->fetch_object()){

          $nick = $post->nick;

          $post_dt = $post->post_dt;

          $post_text = $post->post_text;

         

          echo "<b>$nickb> ($post_dt):<br>";

          echo "$post_text<br>";

          echo "<br>";

        }

        $result->close();

      }

      ?>

      И вставим (добавим) в “getcomments.php” после инициализации MySQL.

      3. Дальше, вырежем недалекий блок MySQL с “index.php”:

      php

      $mysqli->close();

      ?>

      Вставим его в конец файла “getcomments.php”.

      4. Наконец-то, убираем JS-скрипт, который опускает скролл в самый низ.

      <script type="text/javascript">

      var comments = document.getElementById('comments');

      comments.scrollTop = comments.scrollHeight;

      script>

      Не переживай, это только временно.

      5. Сделано. Теперь имеем что-то наподобие этого:

       <html>

      <head>

      head>

      <body>

      <style>

      /* All CSS is very simplified. I provide it for example and no more.

       * In Chrome it works tolerably, but in IE and Firefox it works very poorly.

       */

      .content {

        display: table;

        width: 50%;

        min-width: 400px;

        height: 80%;

        /* Center horizontally and vertically */

        position: absolute;

        left: 0; right: 0;

        top: 0; bottom: 0;

        margin: auto;

        /* Design */

        border: 1px solid;

        background-color: silver;

        padding: 5px;

      }

      /* For mobile devices */

      @media (max-width: 400px) {

        .content {

          width: 100%;

          min-width: 0;

          padding: 0px;

        }

      }

      style>

      <div class="content">

      <div id="comments" style="overflow-y: scroll; height: 100%;">

      div>

      <form action="post.php" method="post" style="height: 0; display: table-row;">

        Nick:<br>

        <input type="text" name="nick" style="width: 100%;">input><br>

        <br>

        Text:<br>

        <textarea name="text" style="width: 100%;">textarea><br>

        <br>

        <input value="Submit" type="submit">input>

      form>

      div>

      body>

      html>

      getcomments.php:

       php

      $mysqli = new mysqli("127.0.0.1", "root", "", "chatdb");

      /* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */

      /* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */

      /* "chatdb" is DB's name. */

      /* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */

      $result = $mysqli->query("SELECT * FROM posts;");

      ?>

      Вероятно, теперь наша страница разделена.

      Давайте проверим её. Переходим http (точнее ССЫЛКА для локального сервера).

      Дальше, переходим на главную страницу, http:///index.php

      Это удивительно! Всё удачно получилось, разделив страницу на части за пару минут!

      Не останавливаемся на этом. Теперь “glue” эти части с помощью AJAX. Как это сделать?

      1. Для начала стоит создать пустой JS-скрипт на главной странице:

      <script type="text/javascript">

      alert('Test');

      script>

      Добавив это после тега div, перед закрывающимся тегом .

      2. Сделаем HTTP GET запрос от JS к “getcommet.php”

      Для этого используем XMLHtttpRequest (XHR) класс:

      <script type="text/javascript">

      var xhr = new XMLHttpRequest();

      xhr.open('GET', '/getcomments.php', false);

      xhr.send(null);

      if (xhr.status == 200) {

        alert(xhr.responseText);

      }

      script>

      Это работает, но не читает старые версии IE те, что не поддерживают такую инициализацию.

      Для получения более кросс-браузерного пути переходим в

      и добавляем это:

      <script type="text/javascript">

      function getXmlHttp(){

        var xmlhttp;

        try {

          xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");

        } catch (e) {

          try {

            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

          } catch (E) {

            xmlhttp = false;

          }

        }

        if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {

          xmlhttp = new XMLHttpRequest();

        }

        return xmlhttp;

      };

      script>

      И главный скрипт (в конце)

      <script type="text/javascript">

      var xhr = getXmlHttp();

      xhr.open('GET', '/getcomments.php', false);

      xhr.send(null);

      if (xhr.status == 200) {

        alert(xhr.responseText);

      }

      script>

      Как видно, теперь JS получает контент со страницы “getcomments.php” и показывает это в предупреждении.

       

      2.1. Вопрос: «Это на самом деле AJAX (Asynchronous Javascript And Xml)?»

      Это AJAX, потому что запрос сервера отформатирован в HTML (который основан на XML).

      Но действительно ли это AJAX, это асинхронно?

      Проверим. Добавим эти уже знакомые строки в любое место между в “getcomments.php”:

      for ($i = 0; $i < 1000000000; $i++) { }

      Что теперь видно на загружаемой странице?

      Вначале страница зависает, его замораживает UI (становится не реагирующим на нажатие левой/правой кнопки мыши):

      Дальше Chrome показывает навязчивое всплывающие окно, сообщающее об удалении страницы:

      Это не AJAX! Это JAX! Как его сделать асинхронным?

      К счастью, ХHR также поддерживает асинхронный режим:

      <script type="text/javascript">

      var xhr = getXmlHttp();

      xhr.open('GET', '/getcomments.php', true); /* true for asynchronous */

      xhr.onreadystatechange = function() {

        if (xhr.readyState == 4) {

          if(xhr.status == 200) {

            alert(xhr.responseText);

          }

        }

      };

      xhr.send(null);

      script>

      В этом случае браузер не ждет ответа с главного потока пользовательского интерфейса, он запускает в другом (асинхронно) и вызываемым событием “onreadystatechange” в главном контексте UI. 

      Теперь всё в порядке, страница полностью доступна, пока запрос запущен, и после ответа получит предупреждение.

      for ($i = 0; $i < 1000000000; $i++) { }

      И продолжаем работу.

      3. Добавляем этот контент в div  вместо предупреждения. Заменить это:

      alert(xhr.responseText); 

      C этим:

      var divComments = document.getElementById('comments');

      divComments.innerHTML = xhr.responseText;

      Возвращаем назад, клиент видит “glued” страницу с блоком комментариев.

      4. Дальше следует установить интервал для автоматической проверки новых комментариев время от времени… и также восстановить удаленный сценарий автоматической прокрутки. 

      <html>

      <head>

      <script type="text/javascript">

          function getXmlHttp() {

              var xmlhttp;

              try {

                  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");

              } catch (e) {

                  try {

                      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

                  } catch (E) {

                      xmlhttp = false;

                  }

              }

              if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {

                  xmlhttp = new XMLHttpRequest();

              }

              return xmlhttp;

          };

      script>

      head>

      <body>

      <style>

      /* All CSS is very simplified. I provide it for example and no more.

       * In Chrome it works tolerably, but in IE and Firefox it works very poorly.

       */

      .content {

        display: table;

        width: 50%;

        min-width: 400px;

        height: 80%;

        /* Center horizontally and vertically */

        position: absolute;

        left: 0; right: 0;

        top: 0; bottom: 0;

        margin: auto;

        /* Design */

        border: 1px solid;

        background-color: silver;

        padding: 5px;

      }

      /* For mobile devices */

      @media (max-width: 400px) {

        .content {

          width: 100%;

          min-width: 0;

          padding: 0px;

        }

      }

      style>

      <div class="content">

      <div id="comments" style="overflow-y: scroll; height: 100%;">

      div>

      <form action="post.php" method="post" style="height: 0; display: table-row;">

        Nick:<br>

        <input type="text" name="nick" style="width: 100%;">input><br>

        <br>

        Text:<br>

        <textarea name="text" style="width: 100%;">textarea><br>

        <br>

        <input value="Submit" type="submit">input>

      form>

      div>

      <script type="text/javascript">

          var divComments = document.getElementById('comments');

          function loadComments() {

              var xhr = getXmlHttp();

              xhr.open('GET', '/getcomments.php', true);

              xhr.onreadystatechange = function () {

                  if (xhr.readyState == 4) {

                      if (xhr.status == 200) {

                          if (xhr.responseText !== divComments.innerHTML) {

                              divComments.innerHTML = xhr.responseText;

                              divComments.scrollTop = divComments.scrollHeight;

                          }

                      }

                  }

              };

              xhr.send(null);

          };

          loadComments();

          setInterval(loadComments, 1000)

      script>

      body>

      html>

      Теперь проблема исправить это. Новые комментарии с другого пользовательского чата (другие вкладки браузеров, окон и экземпляров) получают каждые 1000 миллисекунды (1 секунду) автоматически.

      Но отправка комментариев уже вызывает перезагрузку нашей страницы.

      Отправка комментариев без перезагрузки

      Как написано выше, XHR помогает отправлять HTTP GET-запросы без перезагрузки страницы и GUI заморозки (асинхронно).

      Теперь отправляем HTTP-запрос асинхронно, но на этот раз POST запрос, а не GET.

      И, естественно, XHR позволяет это. Используем метод send(). Для GET указываем null. Для POST устанавливаем запрос “body”.Также нужно добавить “Content-Type:application/x-www-from-urlencoded” в header  для того, чтобы разрешить серверу знать, какой формат использовать для отправки данных.

      Заметка: если не знаете, что отправлять, то можно захватить регулярный запрос с помощью “Fiddler” или же любой другой HTTP-перехватчик и только просимулировать запрос. HTTP-перехватчик — это незаменимый инструмент для работы с HTTP/HTTPS. Это позволяет увидеть все headers и bodies по всем HTTP(S)-запросам, что отправляются в систему. Лучше использовать “Fiddler”, это бесплатное, современное и очень простое приложение, что может поддерживать HTTP/HTTPS и оба Win x86/x64.

      1. Для начала создадим пустой JS скрипт в HTML. Разместить до самого

      тега, потому что этот скрипт будет использован для отправки формы комментария (форма будет вызывать этот скрипт при отправке).2. В этом скрипте, реализуем функцию, что будет отправлять ник и комментарии в “post.php”

       <script type="text/javascript">

      function postComment(nick, text) {

        var xhr = getXmlHttp();

        xhr.open('POST', '/post.php', true);

        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

        xhr.onreadystatechange = function() {

          if (xhr.readyState == 4) {

            if (xhr.status == 200) {

              /* it isn't required to add comment to DOM manually, it will done automatically on next refresh via AJAX */

            }

          }

        };

        xhr.send('nick=' + nick + '&text=' + text); /* joining the data in format simulates form */

      };

      script>

      3. Следующие, перезагружая страницу при отправке: 

      ... onsubmit="return false;">

      Также добавим вызов “postComment’s”:

      action="post.php" method="post" style="height: 0; display: table-row;" onsubmit="postComment(this.nick.value, this.text.value); return false;">

      4. Наконец, необязательно, но можно убрать “action” и “method” с формы:

       <form style="height: 0; display: table-row;" onsubmit="postComment(this.nick.value, this.text.value); return false;">

      5. Результат:

      <html>

      <head>

      <script type="text/javascript">

          function getXmlHttp() {

              var xmlhttp;

              try {

                  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");

              } catch (e) {

                  try {

                      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

                  } catch (E) {

                      xmlhttp = false;

                  }

              }

              if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {

                  xmlhttp = new XMLHttpRequest();

              }

              return xmlhttp;

          };

      script>

      head>

      <body>

      <style>

      /* All CSS is very simplified. I provide it for example and no more.

       * In Chrome it works tolerably, but in IE and Firefox it works very poorly.

       */

      .content {

        display: table;

        width: 50%;

        min-width: 400px;

        height: 80%;

        /* Center horizontally and vertically */

        position: absolute;

        left: 0; right: 0;

        top: 0; bottom: 0;

        margin: auto;

        /* Design */

        border: 1px solid;

        background-color: silver;

        padding: 5px;

      }

      /* For mobile devices */

      @media (max-width: 400px) {

        .content {

          width: 100%;

          min-width: 0;

          padding: 0px;

        }

      }

      style>

      <div class="content">

      <div id="comments" style="overflow-y: scroll; height: 100%;">

      div>

      <script type="text/javascript">

          function postComment(nick, text) {

              var xhr = getXmlHttp();

              xhr.open('POST', '/post.php', true);

              xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

              xhr.onreadystatechange = function () {

                  if (xhr.readyState == 4) {

                      if (xhr.status == 200) {

                          /* it isn't required to add comment to DOM manually, it will done automatically on next refresh via AJAX */

                      }

                  }

              };

              xhr.send('nick=' + nick + '&text=' + text);

          };

      script>

      <form style="height: 0; display: table-row;" onsubmit="postComment(this.nick.value, this.text.value); return false;">

        Nick:<br>

        <input type="text" name="nick" style="width: 100%;">input><br>

        <br>

        Text:<br>

        <textarea name="text" style="width: 100%;">textarea><br>

        <br>

        <input value="Submit" type="submit">input>

      form>

      div>

      <script type="text/javascript">

          var divComments = document.getElementById('comments');

          function loadComments() {

              var xhr = getXmlHttp();

              xhr.open('GET', '/getcomments.php', true);

              xhr.onreadystatechange = function () {

                  if (xhr.readyState == 4) {

                      if (xhr.status == 200) {

                          if (xhr.responseText !== divComments.innerHTML) {

                              divComments.innerHTML = xhr.responseText;

                              divComments.scrollTop = divComments.scrollHeight;

                          }

                      }

                  }

              };

              xhr.send(null);

          };

          loadComments();

          setInterval(loadComments, 1000)

      script>

      body>

      html>

       Теперь простая реализация AJAX подошла к концу. Это ещё не конец, это только начало. Есть ещё достаточно всего для изучения и улучшения.

      КОММЕНТАРИИ И ОБСУЖДЕНИЯ

      Пакеты подписки с доступом ко всем курсам и сервисам

      Стартовый
      • Все видеокурсы на 3 месяца
      • Тестирование по 10 курсам
      • Проверка 5 домашних заданий
      • Консультация с тренером 30 мин
      Базовый
      • Все видеокурсы на 6 месяцев
      • Тестирование по 16 курсам
      • Проверка 10 домашних заданий
      • Консультация с тренером 60 мин
      Премиум
      • Все видеокурсы на 1 год
      • Тестирование по 24 курсам
      • Проверка 20 домашних заданий
      • Консультация с тренером 120 мин
      new
      Премиум Plus
      • Все видеокурсы на 1 год
      • Тестирование по 24 курсам
      • Проверка 20 домашних заданий
      • Консультация с тренером 120 мин
      • Скачивание видео уроков
      Notification success
      Мы используем cookie-файлы, чтобы сделать взаимодействие с нашими веб-сайтами и услугами простым и значимым.