首頁 >web前端 >js教程 >Ajax淺析與實操

Ajax淺析與實操

一个新手
一个新手原創
2017-09-09 10:39:471354瀏覽

開頭那些話

目的

首先鄙人是一名信管人,本科學習的是SSH框架後台java開發(學得一塌糊塗)。平時開發Web專案都是用jsp做頁面直出,然後各種form表單提交,action跳轉;導致一旦需要更新資料就要刷新頁面,哪怕是一小部分地方;很是麻煩,也影響使用者體驗。我就一直想用一種技術來解決這個問題。所以私底下折騰了一陣子,看了看ajax,發現struts2完美支持ajax,所以寫下這篇文章,以供和我有過一樣故事的人參考! (ps:平常私底下班上有同學問過我,所以乾脆整理出來,做參考!)

#事先準備

這篇文章主要是講struts2環境下的ajax應用。所以你事先需要在你的Web專案裡面導入struts2所有相關jar包,這個學過的人都知道,這裡就不多贅述;除此之外還需導入一個額外的jar包,用來支持json數據格式;jar包我會以附件形式發出來。基本上做完這些就可以開始了!


具體實作

具體我會講兩個例子,一個用來講述ajax請求的具體流程,另一個就與實際應用有關了-根據參數傳回對應的數據。

頁面程式碼(HTML+CSS+JS)

先貼程式碼1(為了方便,我就沒有貼jsp程式碼,其實也就標籤一些配置項目而已,讀者可以自己複製)

<!DOCTYPE html><html lang="zh-CN"><head>
  <meta charset="UTF-8">
  <title>XHR</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <style>
    form, .box {      
    margin: 50px;      
    padding: 20px;    
    }

    form p {      
    margin: 20px 0;    
    }

    .box {      
    background-color: rgba(0, 0, 0, 0.2);      
    height: 40px;      
    width: 300px;    
    }
  </style></head><body>
  <form id="form">
    <p><label for="nick">昵称:</label> <input value="jero" name="nick" id="nick" type="text" required></p>
    <p><label for="love">爱好:</label> <input value="coding" name="love" id="love" type="text" required></p>
    <p>
      <button type="button" name="get">Get 提交</button>
      <button type="button" name="post">Post 提交</button>
    </p>
  </form>
  <p id="box" class="box"></p>
  <script>

    var byId = (id) => document.getElementById(id); // ES6 箭头函数
    var form = byId(&#39;form&#39;);    var box = byId(&#39;box&#39;);    /**
     * 表单的数据收集起来
     */
    function getData(type) {
      var result = [];      
      var isFill = false;      // 都是文本框的 name
      [&#39;nick&#39;, &#39;love&#39;].forEach((fieldName) => {        
      var v = form[fieldName].value;        
      var obj = {};        
      if (v) {
         obj[fieldName] = v;
          result.push(obj);
          isFill = true;
        } else {
          isFill = false;
        }
      });      if (!isFill) { // 没填的话要返回没填的结果 false
        return false;
      }
      result = JSON.stringify(result);
      result = "info" + &#39;=&#39; + encodeURIComponent(result) 
      return result;
    }    function request(type, callback) {
      var data = getData(type);      
      if (!data) { // 没填的话直接警告
        return alert("完成表单!");
      }      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = () => {        
      if (xhr.readyState === 4) {
          callback(JSON.parse(xhr.responseText), xhr);
        } else {
          console.log(xhr.status);
        }
      }

      xhr.open(type, &#39;./xhr&#39; + (type === &#39;get&#39; ? `?${data}` : &#39;&#39;)); // get 的参数直接拼在 url 的末尾

      // 模拟 post 请求,必须设置个请求头
      if (type === &#39;post&#39;) {
        xhr.setRequestHeader(&#39;Content-Type&#39;, &#39;application/x-www-form-urlencoded&#39;)//可以自己根据实际情况改变取值
      }

      xhr.send(type === &#39;get&#39; ? null : data);
    }    /**
     * 绑定事件抽象下
     */
    function click(btn, callback) {
      btn.addEventListener(&#39;click&#39;, () => {
        request(btn.name, (data) => {         
        var data = JSON.parse(data);
          box.innerHTML = `success by ${data[0].type} method!<br>
         ${data[0].infoStr}`;
         console.log(data);
        });
      });
    }

    // 绑定事件,代码可以从这里看
    click(form.get);
    click(form.post)  </script></body></html>

頁面運行效果
Ajax淺析與實操
#上面程式碼中有幾處在這說一下。 1.encodeURIComponent()這個函數是用來把變數轉換成url位址中的字串,避免傳值時出現亂碼。 2.當使用var form = document.getElementById('form')取得到form表單節點時,我們可以直接使用form.nickform[nick]來直接取得暱稱輸入框節點,當然前提是form表單中的元素且設定了name屬性。
然後我們來重點解讀下這段程式碼:

function request(type, callback) {      var data = getData(type);//参数列表字符串

      if (!data) { // 没填的话直接警告
        return alert(&#39;完成表单!&#39;);
      }      var xhr = new XMLHttpRequest();//生成XHR对象

      xhr.onreadystatechange = () => {        if (xhr.readyState === 4) {
          callback(JSON.parse(xhr.responseText), xhr);//数据成功接收后的回调函数
        } else {
          console.log(xhr.status);
        }
      }

      xhr.open(type, &#39;./xhr&#39; + (type === &#39;get&#39; ? `?${data}` : &#39;&#39;)); // get 的参数直接拼在 url 的末尾

      // 模拟 post 请求,必须设置个请求头
      if (type === &#39;post&#39;) {
        xhr.setRequestHeader(&#39;Content-Type&#39;, &#39;application/x-www-form-urlencoded&#39;)//可以自己根据实际情况改变取值
      }

      xhr.send(type === &#39;get&#39; ? null : data);
    }

首先,明確一點這個函數的作用就是發送ajax請求;這裡我採用了原生的XHR物件來實現ajax請求,目的是讓大家能夠深刻理解到ajax 是怎麼樣一回事;整體來說發送ajax請求分為四步:

一、創建XHR對象

IE7以上以及現在主流的瀏覽器都支持原生的XHR對象,所以我們可以直接用var xhr = new XMLHttpRequest();來建立XHR對象,用XHR物件所封裝的一些方法來實作ajax請求。至於IE7以下的毒瘤,我絕對不會做考慮的!如果你硬要做IE7以下的兼容可以參考js紅皮書ajax章節。是透過ActiveX物件來創建的!

二、綁定監聽函數

xhr.onreadystatechange實現監聽請求回應過程所處的的階段。主要是透過XHR物件的readyState屬性;屬性的取值為:
0-未初始化(未呼叫open()方法)
1-啟動(呼叫open()方法,未呼叫send()方法)
2-發送(呼叫send()方法,但沒有得到回應、沒有接收到資料)
3-接收(接收到部分資料)
4-完成(得到全部回應資料)
當屬性值每發生一次變化,就觸發一次readystatechange事件。所以我們可以透過這個屬性的值來判斷我們所需的資料是否準備就緒。以便及時地將我們所要求的資料渲染到頁面中去。
xhr.status回傳的則是HTTP請求的狀態碼( 學過網路的同學應該都了解),這就方便我們偵測請求是否成功,也或判斷請求失敗的原因。
callback(JSON.parse(xhr.responseText), xhr);這個則是我們接收到全部資料時所要執行的回呼函數,主要用來處理接收的數據,進行頁面渲染。大家在實際應用時可以照寫,重點是綁定函數中該回呼函數的編寫,大家則要根據實際需求進行編寫。

三、啟動請求

xhr.open(type, &#39;./xhr&#39; + (type === &#39;get&#39; ??${data}: &#39;&#39;));

第一個參數主要設定請求是使用get方法還是post方法,(ps:最近有文章說了這兩者根本沒什麼區別,在這裡我們暫且遵循老套路),第二個則是請求的目標位址,運用了一個三目運算來區分get和post因為get方法的傳參是透過將參數放到url一併發送到後台的,所以我們要進行字串的拼接;而post是透過請求頭中的Form Data傳遞的;如下圖:
Ajax淺析與實操

#

四、发送请求

xhr.send(type === &#39;get&#39; ? null : data);最后一个环节,上面说到的post传参就要在这传入,get则不用,所以在这里同样用了一个三目运算。

基本上,原生的XHR对象实现ajax请求就如上所说;是不是觉得有点复杂?那么不用慌,喜欢“偷懒”的高端程序猿已经帮我们实现了封装;没错就是当初影响世界的jQuery。话不多说,直接上代码:

$.ajax(function() {
    url: &#39;xhr&#39;,
    type: &#39;get&#39;,
    dataType: &#39;json&#39;,//返回数据类型
    data: {info: data},//传参
    success: function(data) {
        /***/
    },
    error: function() {
        console.log(&#39;error!&#39;);
    }
});

jQuery提供了很多种写法,包括更简单的$.getJSON();至于我为什么要推荐这种写法,大家可以理解成我很笨,但是其中的含义大家用过就明白了!(吹个小牛皮)

后台代码(action+struts.xml)

上面说了这么多,一是让大家了解原生的是怎样的一个东西,二是因为上述部分是学习后台同学没有接触过的,所以尽可能的讲清楚点;这部分,我想代码一贴出来,大家都懂了!
action

package com.testforajax.demo.action;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import org.apache.struts2.ServletActionContext;import net.sf.json.JSONArray;import net.sf.json.JSONObject;import com.opensymphony.xwork2.ActionSupport;public class AjaxDemo extends ActionSupport {
    private String info;    public String getInfo() {        return info;
    }    public void setInfo(String info) {        this.info = info;
    }    public String execute() throws Exception {
        String method = ServletActionContext.getRequest().getMethod();
        HashMap<String, String> map = new HashMap<String, String>();
        String name;
        String love;
        JSONArray json = JSONArray.fromObject(info);
        name = json.getJSONObject(0).getString("nick");
        love = json.getJSONObject(1).getString("love");
        json.clear();
        String result = name + " very love " + love;
        map.put("type", method);
        map.put("infoStr", result);
        json.add(map);
        info = json.toString();
        System.out.println(this.info);        return "success";
    }
}

struts.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"><struts>
    <!-- XHR演示 -->
    <package name="xhrTest" extends="json-default, struts-default">
        <action name="xhr" class="com.testforajax.demo.action.AjaxDemo">
            <result type="json">
                <param name="root">info</param>
            </result>
        </action>
        <!--
        <action name="newxhr" class="com.testforajax.demo.action.AjaxDemo2">
            <result type="json">
                <param name="root">queryId</param>
            </result>
        </action>
        -->
    </package></struts>

在这里只强调一点,struts2的自动打包传值,一定要保证参数名一致!即你在前台封装json数据格式时,对应的key值要和struts.xml配置文件中<param name="root">info一致,同时在action类中也要有对应的属性,以及getter和setter。
还有,在使用json数据格式时要做到传参时记得JSON.stringify(),渲染响应数据时记得JSON.parse()。封装时,一定要按照标准格式,后台封装的话,推荐我写的那种先用map做处理。

以上是Ajax淺析與實操的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn