iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 20
1
Modern Web

Half-Stack Developer 養成計畫系列 第 20

讓我們再轉 180 度,更即時的前端:ajax

讓我們再轉 180 度,更即時的前端:ajax

講了這麼多後端的東西,我們現在又要暫時跳回來講一下前端了。之前有說過,每次你要造訪一個新的頁面,都是瀏覽器發一個 request 給 server,server 回傳 response 之後再由瀏覽器 render 出來。所以每個頁面幾乎都是一個不同的檔案,你有可以很明顯地看到瀏覽器跳頁的動作。

可是,你有沒有發現你在用 Gmail 的時候,你沒有感覺過「跳頁」?好像所有的事情都是在同一頁上面發生的,你不會看到你點了某封信以後,畫面就突然全部變白色開始 loading。

這是因為,你點了某封信以後,儘管瀏覽器的確載入了新資料,但卻沒有跳到另外一個新的頁面。這樣的技術,就叫做 AJAX,全名是:Asynchronous JavaScript and XML,非同步的 JavaScript 與 XML。

總之呢,ajax 的應用隨處可見,只要是可以拿到新資料但又沒有跳頁的,你就可以視為是 ajax。例如說你在 Google 搜尋的時候,他下面不是會跳出一堆的建議關鍵字嗎。而且你每打一個字就會跟著變。那是因為你每次打字的時候,都會利用 ajax 送一個 request 到後端,後端再傳回 Google 建議的搜尋關鍵字清單,前端做處理以後再顯示出來。所以這期間其實你一直在跟 Google 的後端做溝通,只是你不知道而已。

那為什麼我們需要 ajax?很間單嘛,就是使用者體驗可以好很多。假設你現在身處於一個沒有 ajax 的年代,你想想會發生什麼事?你在 Google 搜尋的時候就沒有建議關鍵字可以看;你在申請帳號的時候,你必須按下「送出」,他才會告訴你這個帳號有人用了;或者是你用 Gmail,每點進一封信都要切換一次頁面,載入全部的東西。

所以 ajax 的重點就是能在不切換頁面的前提下,發送 request 並且得到 response。我們現在就來把之前完成的留言板改成用 ajax 吧!使用者體驗會好很多。

要用 ajax 的話,最方便的就是用 jQuery 所提供的$.ajax這個方法。(如果你想知道不靠 jQuery 的方法,可參考w3schools

在要把前端改成 ajax 之前,你的後端也必須跟著調整。例如說我們可以先來試試看把刪除文章改成用 ajax,後端的 response 則要輸出成功或者是失敗:

// 刪除文章
app.get('/posts/delete/:id', function (req, res) {
  var id = req.params.id;
  db.deletePost(id, function (err) {
    if (err) {

      // 失敗
      res.send({
        status: 'FAILURE',
        err: err
      });
    } else {

      // 成功後輸出成功
      res.send({
        status: 'SUCCESS'
      });
    }
  })
})

這樣子前端就可以根據 server 回傳的 response 判斷有沒有刪除成功。原本我們的「刪除」按鈕是做成一個超連結直接連去刪除的網頁,現在改用 ajax 之後,就要自己動手寫事件了。

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
  <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
  <script>
    $(document).on('click', '.btn-delete' ,function() {
      var element = $(this);
      var id = element.attr('data-id');
      $.ajax({
        url: '/posts/delete/' + id,
        success: function(response) {
          if (response.status === 'SUCCESS') {

            // 自己刪除這篇文章
            element.parents('.panel').fadeOut();
          } else {
            alert('刪除失敗');
          }
        },
        error: function(err) {
          console.log(err);
          alert('刪除失敗');
        }
      })
    })
  </script>
</head>
<body>
  <div class="container">
    <% if (username) { %>
      <a class="btn btn-default" href="/logout">登出</a>
    <% } else { %>
      <a class="btn btn-default" href="/login">登入</a>
    <% } %>

    <a class="btn btn-primary" href="/posts">發表新留言</a>
    <h2>留言列表</h2>
    <div>
      <% for(var i=0; i<posts.length; i++) { %>
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title"><%= posts[i].author %>, 發佈時間:<%= posts[i].createTime %></h3>
          </div>
          <div class="panel-body">
            <%= posts[i].content  %>
            <% if (isAdmin) { %>
              <a class="btn-delete" data-id="<%= posts[i]._id %>">刪除</a>
            <% } %>
          </div>
        </div>
      <% } %>
    </div>
  </div>
</body>
</html>

這邊可以看到我們更改了兩個部分,第一個是加上了一段 JavaScript 的程式碼,第二個是原本的刪除按鈕換了,我們自訂了一個data-id的屬性來存說到底我們要刪除的是哪一個文章。

JavaScript 的那一段程式碼就是在監聽任何.btn-delete的 click 事件,當被點擊的時候先把 id 抓出來,再用 ajax 發送一個 request 給 server 跟他說我要刪除文章,最後再看 response 決定到底是成功還是失敗。記得成功之後要自己手動寫程式把元素給移除掉,才會有刪除的效果,不然就沒有用了。

在 Chrome dev tool 裡面的 Network tab,可以看到瀏覽器發出的每一個 request。你可以找一些網站來試試看,看你做了一些動作會有哪些 request 發出去。如果跳頁的話,就會整個被清空(除非你把 preserve logs 勾起來)。

除了刪除以外,其實你可以把任何的動作都變成是 ajax。例如說發表文章,你可以設計成按按鈕之後跳出一個視窗讓你輸入資料,按下確認之後透過 ajax 把表單送出。這樣子整個發表文章的流程就會變得很順暢。只是通常使用到 ajax 的時候,都會需要有一個 loading 的小動畫,不然使用者可能不知道他真的有送出資料,就會覺得很奇怪。

總之呢,ajax 的出現讓我們在網頁前端可以做出更好的使用者體驗,不必每一次跟伺服器交換資料就換頁一次。希望你可以試試看把發文或者是登入也改成 ajax 試試看,就當作練習吧!


上一篇
沒那麼簡單~的留言板
下一篇
你走你的陽關道,我走我的獨木橋:前後端分離
系列文
Half-Stack Developer 養成計畫30

1 則留言

0
微中子
iT邦新手 4 級 ‧ 2016-12-30 02:04:35

圖片連結 not work

huli iT邦新手 5 級‧ 2016-12-30 08:52:05 檢舉

感謝 已更新

我要留言

立即登入留言