ajax

問答

一、ajax 是什么?有什么作用?

Ajax是Asynchronous JavaScript and XML的縮寫,通過new XMLHttpRequest創建對象,它是一個具有應用程序接口的JavaScript對象,能夠使用超文本傳輸協議連接1個服務器,是微軟在1999年IE5.0瀏覽器中率先提出的。通過這個對象向服務器請求額外的數據,去獲取數據,而無需卸載整個頁面,帶來良好的用戶體驗。

二、前后端開發聯調需要注意哪些事情?后端接口完成前如何 mock 數據?(npm install -g server-mock)

  • 前后端聯調
    前后端聯調是一種真實業務數據和本地mock數據之間來回切換,以達到前后端分離架構下的不同開發速度時數據交換的一種方式方法。需要注意的有:
  • 數據:需要約定好傳輸的數據以及類型。
  • 接口:確定接口名稱及請求和響應的格式,請求的參數名稱、響應的數據格式。
  • 后端接口完成前mock 數據
  • 可以搭建php本地服務器,php寫腳本提供臨時數據;
  • 也可使用Mock.js,它能攔截ajax請求并根據請求中的內容來隨機生成符合你要求的假數據,模擬后端環境讓你完成對頁面和接口的測試。
  • 也可以安裝server-mock這樣的工具,這樣不需要特地去寫一個后臺的處理頁面文件來訪問數據。

三、點擊按鈕,使用 ajax 獲取數據,如何在數據到來之前防止重復點擊?

  • setTimeout + clearTimeout
    連續的點擊會把上一次點擊清除掉,也就是ajax請求會在最后一次點擊后發出去。
  • disable 按鈕。
  • 給一個flag狀態,用戶點擊后變為false,在數據到來之前不再發送請求,ajax成功后設為true。

代碼

一、封裝一個 ajax 函數,能通過如下方式調用。

function ajax(opts){
    // todo ...
}
document.querySelector('#btn').addEventListener('click', function(){
    ajax({
        url: 'getData.php',   //接口地址
        type: 'get',               // 類型, post 或者 get,
        data: {
            username: 'xiaoming',
            password: 'abcd1234'
        },
        success: function(ret){
            console.log(ret);       // {status: 0}
        },
        error: function(){
           console.log('出錯了')
        }
    })
});
function ajax(opts){
  var req = new XMLHttpRequest();
  req.onreadystatechange = function() {
    if(req.readyState == 4 && req.status == 200)
    {
      console.log(req.responseText)
      var json = JSON.parse(req.responseText);
      opts.success(json);
    }
    if(req.readyState == 4 && req.status == 404)
    {
      opts.error();
    }
  }; //事件監聽函數
  var dataStr = '';
  for(var key in opts.data)
  {
    dataStr += key + '=' + opts.data[key] + '&';
  }
  dataStr = dataStr.substr(0, dataStr.length-1); // var re = /&$/g
  if (opts.type.toLowerCase() === 'post')
  {
    req.open(opts.type, opts.url, true);
    req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    req.send(dataStr);
  }
  if(opts.type.toLowerCase() === 'get')
  {
    req.open(opts.type, opts.url + '?' + dataStr, true);
    req.send();
  }
}
document.querySelector('#btn').addEventListener('click', function(){
    ajax({
        url: 'getData.php',   //接口地址
        type: 'get',               // 類型, post 或者 get,
        data: {
            username: 'xiaoming',
            password: 'abcd1234'
        },
        success: function(ret){
            console.log(ret);       // {status: 0}
        },
        error: function(){
           console.log('出錯了')
        }
    })
});

二、實現如下加載更多的功能。

效果如下: 加載更多
使用server mock工具實現。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>加載更多</title>
</head>
<style>
  *{
    margin: 0;
    padding: 0;
  }
  li{
    list-style: none;
    margin: 8px;
    padding: 4px;
    border: 1px solid #ccc;
    font-size: 25px;
    line-height: 50px;
    cursor: pointer;
  }
  li:hover{
    background: green;
  }
  .btn{
    cursor: pointer;
    padding: 5px;
    margin: 30px 0;
    font-size: 25px;
    line-height: 50px;
    color: purple;
    border: 1px solid red;
    background: #fff;
    outline:none;
  }
  p{
    text-align: center; // 按鈕居中
  }
</style>
<body>
  <ul class="wrap">
    <li>內容1</li>
    <li>內容2</li>
  </ul>
  <p><button class="btn">加載更多</button></p>

  <script type="text/javascript">
    var wrap = document.querySelector('.wrap');
    var btn = document.querySelector('.btn');
    var current = 3;
    var isLoading = false;
    btn.addEventListener('click', function() {
      if(isLoading)
      {
        return;
      }
      isLoading: true;
      btn.innerText = '正在加載,請稍后...';
      ajax({
        url: '/getMore',
        data: {
          start: current,
          len: 6
        },
        success: function(data) {
          isLoading = false;
          btn.innerText = '加載更多';
          if(data.status == 0)
          {
            getMore(data);
            current += 6;
          }else{
            alert('出錯啦')
          }

        },
        error: function() {
          onError();
        }
      });
    });
    function ajax(opts) {
      var req = new XMLHttpRequest();
      req.onreadystatechange = function () {
        if (req.readyState == 4 && req.status == 200)
        {
          var result = JSON.parse(req.responseText);
          opts.success(result);
        }
        if (req.readyState == 4 && req.status == 404)
        {
          opts.error();
        }
      };
      var filter = '';
      for(var key in opts.data)
      {
        filter += key + '=' + opts.data[key] + '&';
      }
      filter = filter.substr(0, filter.length-1);
      req.open('get', opts.url + '?' + filter, true);
      req.send();
    };
    function getMore(data) {
      var data = data.data;
      for (var i=0; i<data.length; i++)
      {
        var li = document.createElement('li');
        li.innerText = '內容' + data[i];
        wrap.appendChild(li);
      }
    }
    function onError() {
      isLoading: false;
      btn.innerText = '加載更多';
      alert('系統異常');
    }
  </script>
</body>
</html>

router.js

app.get('/getMore', function(req, res) {
    // var start = req.query.start,
    //      len = req.query.len;
    var data = [];
    for(var i=0; i<req.query.len; i++)
    {
        data.push(req.query.start++);
    }
    res.send({
        status: 0,
        data: data,
    })
})
請求接收的數據
加載更多

三、實現注冊表單驗證功能

效果如下:表單注冊

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>注冊驗證</title>
  <style>
    form{
      font-size: 20px;
    }
    fieldset label {
      float:left;
      width:120px;
      text-align:right;
      padding:4px;
      margin:1px;
    }
    fieldset div {
      clear:left;
      margin:20px 0;
    }
    input{
      height: 35px;
    }
    .help{
      color: #bbb;
    }
    .submit{
      margin-left: 205px;
    }
    .borderRed{
      border: 1px solid red;
    }
  </style>
</head>
<body>
    <h1>注冊</h1>
    <form id="register" action="" method="post" >
      <fieldset>
        <div>
          <label>用戶名:</label>
          <input class="username" type="text" name="username" placeholder="用戶名(hunger被注冊過)">
          <span class="help usernameWarning">只能是字母、數字、下劃線,3-10個字符</span>
        </div>
        <div>
          <label>密碼:</label>
          <input class="password" type="password" name="pwd">
          <span class="help pwdWarning">大寫字母、小寫、數字、下劃線最少兩種,6-15個字符</span>
        </div>
        <div>
          <label>再輸一次:</label>
          <input class="passwordAgain" type="password" name="pwdAgain" placeholder="再輸入一次密碼">
          <span class="help pwdAgainWarning"></span>
        </div>
        <input class="submit" type="submit" value="注冊"><br/>
      </fieldset>
    </form>
    <script>
      var register = document.querySelector('#register');
      var password = null;
      var submit = document.querySelector('.submit');
      var warning = {
        userExist: "用戶名已經存在",
        usernameformatError: "輸入的用戶名格式不正確,請重新填寫!",
        usernameAvailable: "用戶名可用",
        passwordFormatError: "輸入的密碼格式不正確,請重新設置!",
        passwordAvailable: "密碼可用",
        passwordDifferent: "兩次輸入的密碼不一致!",
      };
      register.addEventListener('focusout', function(e){
        // var className = e.target.className;
        var value = e.target.value;
        var name = e.target.name;
        var className = e.target.className;
        switch(name){
          case 'username':
            checkUser(e, value, className);
            break;
          case 'pwd':
            checkPassword(e, value, className);
            break;
          case 'pwdAgain':
            checkPasswordAgain(e, value, className, password);
            break;
        }
      })
      submit.addEventListener('click', function(e){
        e.preventDefault();
        console.log(document.getElementsByClassName('borderRed'));
        if(document.getElementsByClassName('borderRed').length == 0)
        {
          enroll();
        }
      })
      // 驗證用戶名是否輸入合法
      function checkUser(e, value, className) {
        console.log(e);

        var reg = /^\w{3,10}$/g;
        if(value == "hunger")
        {
          document.querySelector('.usernameWarning').innerText = warning.userExist;
          e.target.className = addClass(className, 'borderRed');
          return false;
        }
        if(!reg.test(value))
        {
          document.querySelector('.usernameWarning').innerText = warning.usernameformatError;
          console.log(document.querySelector('.usernameWarning'));
          console.log(document.getElementsByClassName('username')[0]);
          e.target.className = addClass(className, 'borderRed');
          console.log(className);
          return false;
        }
        if(hasClass(className, 'borderRed'))
        {
          e.target.className = removeClass(className, 'borderRed');
        }
        document.querySelector('.usernameWarning').innerText = warning.usernameAvailable;
        return true;
      }

      // 驗證密碼是否合法  (/\w{,6}|\w{20,}/g).test(value)
      function checkPassword(e, value, className) {
        password = value;
        if((value.length < 6) || (value.length > 15) || ((/[^\w]/g).test(value)) || ((/^[a-z]+$|^[A-Z]+$|^[0-9]+$|^[_]+$/).test(value)))
        {
          document.querySelector('.pwdWarning').innerText = warning.passwordFormatError;
          e.target.className = addClass(className, 'borderRed');
          return false;
        }
        if(hasClass(className, 'borderRed'))
        {
          e.target.className = removeClass(className, 'borderRed');
        }
        document.querySelector('.pwdWarning').innerText = warning.passwordAvailable;
        return true;
      }

      // 兩次密碼是否輸入一致
      function checkPasswordAgain(e, value, className, password) {
        if(value != password)
        {
          console.log(document.querySelector('.passwordAgain'));
          document.querySelector('.pwdAgainWarning').innerText = warning.passwordDifferent;
          e.target.className = addClass(className, 'borderRed');
          return false;
        }
        if(hasClass(className, 'borderRed'))
        {
          e.target.className = removeClass(className, 'borderRed');
        }
        document.querySelector('.pwdAgainWarning').innerText = '';
        return true;
      }

      // 發送數據
      function enroll() {
        ajax({
          url: '/register',
          type: 'post',
          data: {
            username: document.querySelector('.username').value,
            password: document.querySelector('.password').value,
          },
          success: function(list) {
            alert(list.msg);
          },
          error: function() {
            alert("出錯啦");
          }
        })
      }

      function ajax(opts) {
        var req = new XMLHttpRequest();
        req.onreadystatechange = function() {
          if(req.readyState == 4 && req.status == 200)
          {
            var json = JSON.parse(req.responseText);
            opts.success(json);
          }
          if(req.readyState == 4 && req.status == 404)
          {
            opts.error();
          }
        }
        var dataStr = '';
        for (var key in opts.data)
        {
          dataStr += key + '=' + opts.data[key] + '&';
        }
        dataStr = dataStr.substr(0, dataStr.length-1);
        req.open(opts.type, opts.url, true);
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        req.send(dataStr);
      }

      function hasClass(className, cls) {
        var reg = new RegExp('(\\s|^)' + cls + '(\\b|$)', 'g');
        return reg.test(className)
      }
      function addClass(className, cls) {
        if (!hasClass(className, cls)) {
          return className += ' ' + cls;
        }
        return className; // 不要忘記return
      }
      function removeClass(className, cls) {
        if (hasClass(className, cls)) {
          var reg = new RegExp('(\\s|^)' + cls + '(\\b|$)', 'g');
          return className = className.replace(reg, '').replace(/\s{2,}/g, ' ');
        }
        return className; // 不要忘記return
     }

    </script>
</body>
</html>

router.js

// 注冊
app.post('/register', function(req, res) {
    // var start = req.query.start,
    //      len = req.query.len;
    res.send({
        status: 0,
        msg: "恭喜你,注冊成功!",
    })
})
請求接受的數據

注冊
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,619評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,155評論 3 425
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,635評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,539評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,255評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,646評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,655評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,838評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,399評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,146評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,338評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,893評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,565評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,983評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,257評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,059評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,296評論 2 376

推薦閱讀更多精彩內容

  • 瀏覽器與服務器之間,采用HTTP協議通信。用戶在瀏覽器地址欄鍵入一個網址,或者通過網頁表單向服務器提交內容,這時瀏...
    徐國軍_plus閱讀 371評論 0 4
  • AJAX 原生js操作ajax 1.創建XMLHttpRequest對象 var xhr = new XMLHtt...
    碧玉含香閱讀 3,247評論 0 7
  • 關鍵詞:Ajax 1. Ajax 是什么?有什么作用? Ajax 全稱“Asynchronous Javascri...
    NathanYangcn閱讀 322評論 0 0
  • 問答 1. ajax 是什么?有什么作用? Ajax是Asynchronous JavaScript and XM...
    Maggie_77閱讀 405評論 0 0
  • 1. ajax 是什么?有什么作用? Ajax(['eid??ks])是Asynchronous JavaScri...
    曉風殘月1994閱讀 399評論 0 0