課時1 1.ajax簡介(異步與同步)
asynchronous javascript and xml
異步js和xml
1、異步交互和同步交互
同步 發送,等待 整個頁面刷新
異步 發送,不等待 局部刷新
示例:異步刷新
<button id="btn">點擊</button>
<h2 id="text"></h2>
<script>
// 文檔加載完成後馬上執行
window.onload = function(){
let btn = document.getElementById("btn");
// 給btn註冊點擊事件監聽
btn.onclick = function(){
let text = document.getElementById("text");
text.innerHTML= "hello!";
}
}
</script>
課時2 2.異步和同步交互圖
數據格式
text、xml、json
同步:
請求 ->
響應 <-
請求 ->
響應 <-
異步:
請求 ->
請求 ->
響應 <-
響應 <-
課時3 3.ajax的應用場景和優缺點
優點:
異步交互,增強用戶體驗
性能:只需要響應部分內容,服務器壓力減少
缺點:
ajax不能應用在所有場景
ajax增多了對服務器的請求,給服務器增加壓力
課時4 4.ajax四步操作
1、獲取XMLHttpRequest
// 大多數瀏覽器
var xmlHttp = new XMLHttpRequest();
// IE6.0
var xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
// IE<=5.5
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
編寫一個創建XMLHttpRequest對象的函數
function createXMLHttpRequest(){
try{
// 大多數瀏覽器
return new XMLHttpRequest();
}catch(e){
try{
// IE6.0
new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
// IE<=5.5
new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
console.log("瀏覽器版本太老了!");
throw e;
}
}
}
}
2、連接服務器
xmlHttp.open("GET", "/url", true);
// 參數:請求方式,請求url,是否爲異步
3、發送請求
xmlHttp.send(null);
// 參數:請求體內容,如果是GET,必須給出null,不然FireFox可能不發送
4、註冊事件監聽器
(1)5個狀態:
0 剛創建
1 請求開始,調用open
2 請求發送完成 調用send
3 服務器開始響應
4 服務器響應結束
(2)獲取響應內容
// 獲取狀態
var state = xmlHttp.readyState;
// 得到服務器響應狀態碼 200, 404, 500
var status = xmlHttp.status;
// 得到服務器響應內容
var content = xmlHttp.responseText; // 文本格式
var content = xmlHttp.responseXml; // xml格式,document對象
(3)註冊監聽事件
xmlHttp.onreadystatechange = function(){
// 雙重判斷 xmlHttp狀態爲服務器響應結束,服務器狀態響應結束
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
var text = xmlHttp.responseText;
}
}
課時5 5.ajax第一例:helloworld
爲了便於測試,服務端使用Python語言
服務端 hello.py
# pip install flask, flask-cors
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app, supports_credentials=True)
@app.route("/")
def index():
return "<h2>Hello!</h2>"
if __name__ == '__main__':
app.run()
客戶端 demo.html
<button id="btn">點擊</button>
<h2 id="text"></h2>
<script>
// 獲取XMLHttpRequest對象
function createXMLHttpRequest(){
try{
// 大多數瀏覽器
return new XMLHttpRequest();
}catch(e){
try{
// IE6.0
new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
// IE<=5.5
new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
console.log("瀏覽器版本太老了!");
throw e;
}
}
}
}
// 文檔加載完成後馬上執行
window.onload = function(){
let btn = document.getElementById("btn");
// 給btn點擊事件註冊監聽
btn.onclick = function(){
let xmlHttp = createXMLHttpRequest();
xmlHttp.open("GET", "http://127.0.0.1:5000/", true);
xmlHttp.send();
xmlHttp.onreadystatechange = function(){
// 雙重判斷 xmlHttp狀態爲服務器響應結束,服務器狀態響應結束
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
var text = xmlHttp.responseText;
let h2 = document.getElementById("text");
h2.innerHTML= text;
}
}
}
}
</script>
6.ajax第二例:發送POST請求
多添加一個請求頭
// 設置請求頭
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 發送請求體
xmlHttp.send("username=Tom&age=23");
服務端接收函數 hello.py
@app.route("/post", methods=['POST'])
def post():
username = request.form.get("username")
age = request.form.get("age")
return f"<h2>username: {username}, age: {age}</h2>"
客戶端修改 demo.html
xmlHttp.open("POST", "http://127.0.0.1:5000/post", true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttp.send("username=Tom&age=23");
課時7 7.ajax第三例:用戶名是否已被註冊
客戶端要求:
1、註冊表單
2、監聽用戶名文本框失去焦點onblur事件
3、獲取文本框內容,通過ajax異步發送給服務器
4、如果爲1 顯示:用戶名已被註冊
如果爲0 什麼都不顯示
<meta charset="utf-8">
<style>
#errorText {
color: red;
}
</style>
<form action="">
<input type="text" name="username" id="username">
<span id="errorText"></span>
</form>
<script>
// 獲取XMLHttpRequest對象
function createXMLHttpRequest() {
try {
// 大多數瀏覽器
return new XMLHttpRequest();
} catch (e) {
try {
// IE6.0
new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
// IE<=5.5
new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
console.log("瀏覽器版本太老了!");
throw e;
}
}
}
}
// 文檔加載完成後馬上執行
window.onload = function () {
let username = document.getElementById("username");
// 失去焦點註冊事件監聽
username.onblur = function () {
let xmlHttp = createXMLHttpRequest();
xmlHttp.open("POST", "http://127.0.0.1:5000/validate", true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttp.send("username=" + username.value);
xmlHttp.onreadystatechange = function () {
// 雙重判斷 xmlHttp狀態爲服務器響應結束,服務器狀態響應結束
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
var text = xmlHttp.responseText;
let errorText = document.getElementById("errorText");
if (text == '1') {
errorText.innerHTML = "用戶名已被註冊";
} else {
errorText.innerHTML = "";
}
}
}
}
}
</script>
服務端要求:
1、獲取客戶端傳遞的用戶名參數
2、判斷是否爲demo,是返回1,否返回0
@app.route("/validate", methods=['POST'])
def validate():
username = request.form.get("username")
if username == "demo":
return "1"
else:
return "0"
課時8 8.ajax第四例:響應內容爲xml
服務端響應頭
Content-Type: text/xml; charset=utf-8
客戶端設置
var doc = xmlHttp.responseXML; // 得到Document對象
服務端代碼
@app.route("/xml")
def xml():
data = """
<person>
<name>Tom</name>
<age>23</age>
</person>
"""
res = make_response(data)
res.headers['Content-Type'] = 'text/xml; charset=utf-8'
return res
客戶端代碼
<button id="btn">點擊</button>
<h2 id="text"></h2>
<script>
// 獲取XMLHttpRequest對象
function createXMLHttpRequest() {
try {
// 大多數瀏覽器
return new XMLHttpRequest();
} catch (e) {
try {
// IE6.0
new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
// IE<=5.5
new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
console.log("瀏覽器版本太老了!");
throw e;
}
}
}
}
// 判斷是否爲IE瀏覽器
function isIE() {
if (window.addEventListener) {
return false;
} else {
return true;
}
}
// 文檔加載完成後馬上執行
window.onload = function () {
let btn = document.getElementById("btn");
// 註冊事件監聽
btn.onclick = function () {
let xmlHttp = createXMLHttpRequest();
xmlHttp.open("GET", "http://127.0.0.1:5000/xml", true);
xmlHttp.send(null);
xmlHttp.onreadystatechange = function () {
// 雙重判斷 xmlHttp狀態爲服務器響應結束,服務器狀態響應結束
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
// 獲取響應結果
var doc = xmlHttp.responseXML;
// IE 和非IE有所區別
let name = doc.getElementsByTagName("name")[0].textContent;
let age = doc.getElementsByTagName("age")[0].textContent;
let text = document.getElementById("text");
text.innerHTML = `name: ${name}, age: ${age}`;
}
}
}
}
</script>
課時9-10 ajax第五例:省市聯動
<select name="province" id="">
<option value="">請選擇省份</option>
</select>
<select name="city" id="">
<option value="">請選擇城市</option>
</select>
服務端提供兩個接口
province
city?province=北京
完整代碼
一、前端代碼
1、util.js
// 獲取XMLHttpRequest對象
function createXMLHttpRequest() {
try {
// 大多數瀏覽器
return new XMLHttpRequest();
} catch (e) {
try {
// IE6.0
new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
// IE<=5.5
new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
console.log("瀏覽器版本太老了!");
throw e;
}
}
}
}
// 判斷是否爲IE瀏覽器
function isIE() {
if (window.addEventListener) {
return false;
} else {
return true;
}
}
2、demo.html
<select name="province" id="province">
<option value="">請選擇省份</option>
</select>
<select name="city" id="city">
<option value="">請選擇城市</option>
</select>
<script src="./util.js"></script>
<script>
function createOption(name) {
// 創建option元素
let option = document.createElement("option");
option.value = name;
// 創建文本節點
let textNode = document.createTextNode(name);
option.appendChild(textNode);
return option;
}
// 文檔加載完成後馬上執行
window.onload = function () {
// 第一步:先獲取省級列表
let xmlHttp = createXMLHttpRequest();
xmlHttp.open("GET", "http://127.0.0.1:5000/provinces", true);
xmlHttp.send(null);
let province = document.getElementById("province");
xmlHttp.onreadystatechange = function () {
// 雙重判斷 xmlHttp狀態爲服務器響應結束,服務器狀態響應結束
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
// 獲取響應結果
var text = xmlHttp.responseText;
let list = text.split("|"); // 拆分數據得到數組
for (let item of list) {
let option = createOption(item);
province.appendChild(option);
}
}
}
// 第二步:監聽省級列表變動,獲取城市列表
province.onchange = function () {
if (province.value == "") {
return
}
let xmlHttp = createXMLHttpRequest();
xmlHttp.open("POST", "http://127.0.0.1:5000/cities", true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttp.send(`province=${province.value}`);
xmlHttp.onreadystatechange = function () {
// 雙重判斷 xmlHttp狀態爲服務器響應結束,服務器狀態響應結束
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
// 移除所有結果
let city = document.getElementById("city");
let optionList = city.getElementsByTagName("option");
while (optionList.length > 1) {
city.removeChild(optionList[1]);
}
// 獲取響應結果
var doc = xmlHttp.responseXML;
let cities = doc.getElementsByTagName("city");
for (let item of cities) {
let cityName = "";
// 兼容IE瀏覽器和其他瀏覽器
if (isIE()) {
cityName = item.text; // IE
} else {
cityName = item.textContent; // FireFox等
}
let option = createOption(cityName);
city.appendChild(option);
}
}
}
}
}
</script>
二、後端代碼
1、數據文件china.xml
<china>
<province name="北京">
<city>東城區</city>
<city>西城區</city>
</province>
<province name="天津">
<city>和平區</city>
<city>河東區</city>
</province>
</china>
2、數據解析文件demo.py
# pip install lxml
from lxml import etree
class China():
path = "china.xml"
@classmethod
def getProvinces(cls):
"""獲取省份
"""
tree = etree.parse(cls.path)
return tree.xpath('//province/@name')
@classmethod
def getCities(cls, province):
"""獲取城市
"""
tree = etree.parse(cls.path)
result = tree.xpath(f"//province[@name='{province}']")
if result:
return etree.tostring(result[0], encoding="UTF-8")
else:
return ""
if __name__ == "__main__":
print(China.getProvinces())
print(China.getCities("北京"))
3、接口文件
from flask import Flask, request, make_response
from flask_cors import CORS
from demo import China
app = Flask(__name__)
CORS(app, supports_credentials=True)
@app.route("/provinces")
def provinces():
return "|".join(China.getProvinces())
@app.route("/cities", methods=['POST'])
def cities():
province = request.form.get("province")
res = make_response(China.getCities(province))
res.headers['Content-Type'] = 'text/xml; charset=utf-8'
return res
if __name__ == '__main__':
app.run(debug=True)
課時11 11.XStream(可把Javabean轉換成XMl的小工具)
依賴
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2.2</version>
</dependency>
代碼實例
import com.thoughtworks.xstream.XStream;
import java.util.ArrayList;
import java.util.List;
class City {
private String name;
public City(String name) {
this.name = name;
}
}
class Province {
private String name;
private List<City> cities = new ArrayList<>();
public void addCity(City city){
cities.add(city);
}
public Province(String name) {
this.name = name;
}
}
public class TestXStream {
public static void main(String[] args) {
// 數據準備
List<Province> list = new ArrayList<Province>();
Province province = new Province("北京");
province.addCity(new City("東城區"));
province.addCity(new City("昌平區"));
list.add(province);
XStream xStream = new XStream();
// 指定別名
xStream.alias("china", List.class);
xStream.alias("province", Province.class);
xStream.alias("city", City.class);
// 屬性設置
xStream.useAttributeFor(Province.class, "name");
// 去除無用的標籤
xStream.addImplicitCollection(Province.class, "cities");
String str = xStream.toXML(list);
System.out.println(str);
}
}
課時12 12.JSON的概述
js提供的一種數據交換格式
Json語法
屬性名必須使用雙引號括起來
對象:{}
屬性:
null、數值、字符串、數組[]、boolean(true/false)
var s = "1 + 2";
eval(s);
// 3
1、示例
(1)服務端代碼
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app, supports_credentials=True)
@app.route("/json")
def json():
return jsonify({"name": "Tom"})
if __name__ == '__main__':
app.run(debug=True)
(2)客戶端代碼
<button id="btn">點擊</button>
<h2 id="text"></h2>
<script src="./util.js"></script>
<script>
// 文檔加載完成後馬上執行
window.onload = function () {
let btn = document.getElementById("btn");
btn.onclick = function () {
let xmlHttp = createXMLHttpRequest();
xmlHttp.open("GET", "http://127.0.0.1:5000/json", true);
xmlHttp.send(null);
xmlHttp.onreadystatechange = function () {
// 雙重判斷 xmlHttp狀態爲服務器響應結束,服務器狀態響應結束
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
// 獲取響應結果
let text = xmlHttp.responseText;
let obj = JSON.parse(text);
document.getElementById("text").innerHTML = `name: ${obj.name}`;
}
}
}
}
</script>
json與xml比較
可讀性
解碼難度
流行度
課時13 13.json-lib的應用
繼承關係
public final class JSONArray extends AbstractJSON
implements JSON, List, Comparable
public final class JSONObject extends AbstractJSON
implements JSON, Map, Comparable
依賴
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
示例
import net.sf.json.JSONObject;
class Demo {
public static void main(String[] args) {
JSONObject map = new JSONObject();
map.put("name", "Tom");
map.put("age", 23);
String str = map.toString();
System.out.println(str);
// {"name":"Tom","age":23}
}
}
java對象轉爲json
Person.java
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Demo.java
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Demo {
public static void main(String[] args) {
// 對象轉JSONObject
Person person = new Person("Tom", 23);
JSONObject obj = JSONObject.fromObject(person);
System.out.println(obj.toString());
// {"name":"Tom","age":23}
// List轉 JSONArray
List<Person> list = new ArrayList<Person>();
list.add(new Person("Tom", 23));
list.add(new Person("Jack", 23));
JSONArray array = JSONArray.fromObject(list);
System.out.println(array.toString());
// [{"age":23,"name":"Tom"},{"age":23,"name":"Jack"}]
// map轉JSONObject
Map<String ,String> map = new HashMap<String ,String>();
map.put("name", "Tom");
map.put("sex", "male");
System.out.println(JSONObject.fromObject(map).toString());
// {"sex":"male","name":"Tom"}
}
}
課時14 14.打包ajax生成小工具
參數
option{
method
url
asyn
type
callback
params
data
}
xml
text
json
後端接口
from flask import Flask, request, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app, supports_credentials=True)
@app.route("/json", methods=["GET", "POST"])
def json():
username = request.args.get("username")
if request.method == "POST":
username = request.form.get("username")
if request.is_json:
username = request.json.get("username")
return jsonify({"name": username})
if __name__ == '__main__':
app.run(debug=True)
封裝的工具 ajax-util.js
// 獲取XMLHttpRequest對象
function createXMLHttpRequest() {
try {
// 大多數瀏覽器
return new XMLHttpRequest();
} catch (e) {
try {
// IE6.0
new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
// IE<=5.5
new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
console.log("瀏覽器版本太老了!");
throw e;
}
}
}
}
// 判斷是否爲IE瀏覽器
function isIE() {
if (window.addEventListener) {
return false;
} else {
return true;
}
}
/**
* 將對象轉爲url查詢參數
* @param {*} data
* { "name": "Tom", "age": 23 }
* -> name=Tom&age=23
*/
function encodeData(data) {
if (!data) {
return null;
}
let list = [];
for (let [key, value] of Object.entries(data)) {
list.push(`${key}=${value}`);
}
return list.join("&");
}
const CONTENT_TYPE = "Content-Type";
const contentTypeMap = {
html: "text/html; charset=utf-8",
xml: "text/xml; charset=utf-8",
json: "application/json; charset=utf-8",
form: "application/x-www-form-urlencoded"
}
/**
*
* @param {*} option:
* method
* url
* asyn
* type
* callback
* params
* data
*/
function ajax(option) {
// 必傳參數
let url = option.url;
let callback = option.callback;
// 可選參數
let method = option.method || "GET";
let asyn = option.asyn || true;
let params = option.params || {};
let type = option.type || "html";
let data = option.data || {};
let xmlHttp = createXMLHttpRequest();
// 處理響應數據
xmlHttp.onreadystatechange = function () {
// 雙重判斷 xmlHttp狀態爲服務器響應結束,服務器狀態響應結束
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
// 獲取響應結果
let responseData = null;
if (xmlHttp.responseXML) {
responseData = xmlHttp.responseXML;
}
else {
responseData = xmlHttp.responseText;
try {
responseData = JSON.parse(responseData);
} catch (e) {
}
}
callback(responseData);
}
}
// 處理請求數據
if (params) {
url = url + "?" + encodeData(params);
}
xmlHttp.open(method, url, asyn);
xmlHttp.setRequestHeader(CONTENT_TYPE, contentTypeMap[type]);
let sendData = null;
if (type == "json") {
sendData = JSON.stringify(data);
} else {
sendData = encodeData(data);
}
xmlHttp.send(sendData);
}
// console.log(encodeData(undefined));
測試代碼
<button id="get-btn">GET</button>
<h2 id="get-text"></h2>
<button id="post-btn">POST</button>
<form action="">
<input type="text" name="username" id="username">
</form>
<h2 id="post-text"></h2>
<script src="./ajax-util.js"></script>
<script>
// 文檔加載完成後馬上執行
window.onload = function () {
// get方法
let getBtn = document.getElementById("get-btn");
getBtn.onclick = function () {
ajax({
url: "http://127.0.0.1:5000/json",
method: "GET",
params: {
"username": "Tom"
},
callback: function (data) {
console.log(data);
document.getElementById("get-text").innerHTML = data.name;
}
})
};
// post方法
let postBtn = document.getElementById("post-btn");
postBtn.onclick = function () {
ajax({
url: "http://127.0.0.1:5000/json",
method: "POST",
type: "json",
params: {
"username": "Tom"
},
data: {
"username": document.getElementById("username").value
},
callback: function (data) {
console.log(data);
document.getElementById("post-text").innerHTML = data.name;
}
})
}
}
</script>