一文带你迅速入门AJAX,适合零基础小白

233 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第31天,点击查看活动详情

原生AJAX

AJAX简介

  • AJAX即Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
  • AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
  • 通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:==无刷新获取数据==,即在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
  • AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

  • 最开始AJAX进行数据交换时所使用的格式就是XML,服务器给客户端浏览器返回结果时返回的就是XML格式的字符串,现在已经被JSON取代了。
  • XML:可扩展标记语言。XML被设计用来传输和存储数据,而HTML用来呈现数据。XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据。

AJAX的特点

AJAX的优点:

  • 可以无需刷新页面而与服务器端进行通信。
  • 允许你根据用户事件来更新部分页面内容。

AJAX的缺点:

  • 没有浏览历史,不能回退。

  • 存在跨域问题(同源)。

  • 对SEO优化和爬虫不友好。

AJAX请求状态

==XMLHttpRequest.readyState== 属性返回一个 XMLHttpRequest 代理当前所处的状态。一个 XHR 代理总是处于下列状态中的一个: 0:表示XMLHttpRequest实例已经生成,但是open()方法还没有被调用。 1:表示send()方法还没有被调用,仍然可以使用setRequestHeader(),设定HTTP请求的头信息。 2:表示send()方法已经执行,并且头信息和状态码已经收到。 3:表示正在接收服务器传来的body部分的数据。 4:表示服务器数据已经完全接收,或者本次接收已经失败了。

服务器server.js搭建

1.安装Node.js 2.安装express(服务端框架) 2.1初始化环境npm init --yes 2.2下载express包npm i express 3.编写服务器js代码

//server.js:
//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/get-server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //设置响应体
    response.send('HELLO GET');
});
app.post('/post-server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //设置响应体
    response.send('HELLO POST');
});
app.all('/json-server', (request, response) => {
  // 设置响应头, 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*');
  // 设置响应头, 设置允许自定义头信息
  response.setHeader('Access-Control-Allow-Headers', '*');
  // 响应一个数据
  const data = {
    name: 'zag666'
  };
  // 对 对象 进行 字符串 转换
  let str = JSON.stringify(data)
  // 设置响应体 
  response.send(str);
});
4. 监听端口启动服务
app.listen(8000, () => {
    console.log("服务已经启动, 8000 端口监听中....");
});

4.运行server.js:node server.js 5.另外还可以安装nodemon自动重启工具(文件内容有修改自动重新启动服务):npm install -g nodemon;启动:ndoemon server.js

AJAX的使用

1.GET、POST

1)创建XMLHttpRequest对象 XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在 AJAX编程中被大量使用。 var xhr=new XMLHttpRequest(); 2)设置请求信息 xhr.open(method,url); e.g.: xhr.open('GET','http://127.0.0.1:8000/json-server'); xhr.open('POST', 'http://127.0.0.1:8000/server'); 可以设置请求头,一般不设置:xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); 3)发送请求 xhr.send()//get请求不传body参数 xhr.send('a=100&b=200&c=300');post请求传参 4)接收响应

//xhr.responseXML接收xml格式的响应数据
//xhr.responseText接收文本格式的响应数据
xhr.onreadystatechange = function(){
    if(xhr.readyState === 4){
        if(xhr.status >= 200 && xhr.status < 300){
            // console.log(xhr.response);
            // result.innerHTML = xhr.response;
            // 1. 手动对数据转化
            // let data = JSON.parse(xhr.response);
            // console.log(data);
            // result.innerHTML = data.name;
            // 2. 自动转换
            console.log(xhr.response);
            result.innerHTML = xhr.response.name;
        }
    }
}

2.JSON

//json.html:
<body>
  <div id="result"></div>
  <script>
    const result = document.getElementById('result');
    // 绑定键盘按下事件
    window.onkeydown = function(){
      // 发送请求
      const xhr = new XMLHttpRequest();
      // *2*.(自动转换) 设置响应体数据的类型(自动转换)
      xhr.responseType = 'json';
      // 初始化
      xhr.open('GET', 'http://127.0.0.1:8000/json-server');
      // 发送
      xhr.send();
      // 事件绑定
      xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
          if(xhr.status >= 200 && xhr.status < 300){
            console.log(xhr.response);
            // 1. 手动对数据转化 (字符串再转换成json)
            // let data = JSON.parse(xhr.response); //转换成json
            // result.innerHTML = data.name;
            // *2*. (自动转换)自动转换(自动转换)
            result.innerHTML = xhr.response.name; //已经自动变成json
          }
        }
      }
    }
  </script>
</body>

3.重复请求问题、手动取消请求、超时和网络异常

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>重复请求问题</title>
    <style>
        #result{
            width:200px;
            height:100px;
            border:solid 1px #90b;
        }
    </style>
</head>
<body>
    <div id="result"></div>
    <button>点击发送(重复请求问题)</button>
    <button>点击发送(手动取消请求)</button>
    <button>点击发送(超时和网络异常)</button>
    <script>
        //获取元素对象
        const btns = document.querySelectorAll('button');
        const result = document.querySelector('#result');
        let x = null;
        let isSending = false; // 是否正在发送AJAX请求

        //1.重复请求问题
        btns[0].onclick = function(){
            if(isSending) x.abort();// 如果正在发送, 则取消该请求, 创建一个新的请求
            x = new XMLHttpRequest();
            isSending = true;
            x.open("GET",'http://127.0.0.1:8000/delay');
            x.send();
            x.onreadystatechange = function(){
                if(x.readyState === 4){
                    //修改标识变量
                    isSending = false;
                }
            }
        }

        //2.手动取消请求
        btns[1].onclick = function(){
            x = new XMLHttpRequest();
            x.abort();
            console.log(x);
        }

        //3.超时和网络异常
        btns[2].onclick = function(){
            const xhr = new XMLHttpRequest();
            //超时设置 2s 设置
            xhr.timeout = 2000;
            //超时回调
            xhr.ontimeout = function(){
                alert("网络异常, 请稍后重试!!");
            }
            //网络异常回调
            xhr.onerror = function(){
                alert("你的网络似乎出了一些问题!");
            }

            xhr.open("GET",'http://127.0.0.1:8000/delay');
            xhr.send();
            xhr.onreadystatechange = function(){
                if(xhr.readyState === 4){
                    if(xhr.status >= 200 && xhr.status< 300){
                        result.innerHTML = xhr.response;
                    }
                }
            }
        }
    </script>
</body>
</html>

==具体使用案例==可参考:这个

IE缓存问题

问题: 在一些浏览器中(IE),由于缓存机制的存在,ajax只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。 解决方式: 浏览器的缓存是根据url地址来记录的,所以我们只需要修改url地址加一个唯一时间戳即可避免缓存问题 xhr.open("get","/testAJAX?t="+Date.now());

HTTP

HTTP请求响应过程: 前后浏览器端向服务器发送HTTP 请求(请求报文),后台服务器接收到请求后处理请求, 向浏览器端返回HTTP响应(响应报文),浏览器端接收到响应, 解析显示响应体。

一般http请求 与 ajax请求的区别

  • ajax请求 是一种特别的 http请求。
  • 对服务器端来说, 没有任何区别, 区别在浏览器端。
  • 浏览器端发请求: 只有XHR 或fetch 发出的才是ajax 请求, 其它所有的都是非ajax 请求。
  • 浏览器端接收到响应。 (1) 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/跳转页面。 (2) ajax请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调函数并传入响应相关数据。

请求报文

行      POST  /s?ie=utf-8  HTTP/1.1 
头      Host: atguigu.com
        Cookie: name=guigu
        Content-type: application/x-www-form-urlencoded
        User-Agent: chrome 83
空行
体      username=admin&password=admin

响应报文

行      HTTP/1.1  200  OK
头      Content-Type: text/html;charset=utf-8
        Content-length: 2048
        Content-encoding: gzip
空行    
体      <html>
            <head>
            </head>
            <body>
                <h1>abc</h1>
            </body>
        </html>

在这里插入图片描述

jQuery中的AJAX

GET请求

$.get(url, [data], [callback], [type])

url:请求的URL 地址 data:请求携带的参数 callback:载入成功时回调函数 type:设置返回内容格式,xml, html, script, json, text, _default

POST请求

$.post(url, [data], [callback], [type])

url:请求的URL 地址 data:请求携带的参数 callback:载入成功时回调函数 type:设置返回内容格式,xml, html, script, json, text, _default

AJAX

$.ajax({
	// url
	url: 'http://127.0.0.1:8000/jquery-server',
	// 参数
	data: {a:100, b:200},
	// 请求类型
	type: 'GET',
	// 响应体结果
	dataType: 'json',
	// 成功的回调
	success: function(data){console.log(data);},
	// 超时时间
	timeout: 2000,
	// 失败的回调
	error: function(){console.log('出错拉~');},
	// 头信息
	headers: {
		c: 300,
		d: 400
	}	
})

跨域

同源策略

  • 同源策略(Same-Origin Policy)最早由Netscape 公司提出,是浏览器的一种安全策略。
  • 同源: 协议、域名、端口号必须完全相同。
  • 跨域: 违背同源策略就是跨域。

如何解决跨域

1.JSONP

  • JSONP 是什么 JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get 请求。
  • JSONP 怎么工作的? 在网页有一些标签天生具有跨域能力,比如:img link iframe script。 JSONP 就是利用script 标签的跨域能力来发送请求的。
  • JSONP 的使用:

1.动态的创建一个script标签 var script=document.createElement("script"); 2.设置script的src,设置回调函数

script.src = "http://localhost:3000/testAJAX?callback=abc";
function abc(data) {
	alert(data.name);
};

3.将script添加到body中 document.body.appendChild(script); 4.服务器中路由的处理

router.get("/testAJAX" , function (req , res) {
	console.log("收到请求");
	var callback = req.query.callback;
	var obj = {
		name:"孙悟空",
		age:18
	}
	res.send(callback+"("+JSON.stringify(obj)+")");
});
  • JQuery 中的JSONP
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>Title</title>
	</head>
	<body>
		<button id="btn">按钮</button>
		<ul id="list"></ul>
		<script type="text/javascript" src="./jquery-1.12.3.js"></script>
		<script type="text/javascript">
			window.onload = function () {
				var btn = document.getElementById('btn')
				btn.onclick = function () {
					$.getJSON("http://api.douban.com/v2/movie/in_theaters?callback=?",function(data) {
						console.log(data);
						//获取所有的电影的条目
						var subjects = data.subjects;
						//遍历电影条目
						for(var i=0 ; i<subjects.length ; i++){
							$("#list").append("<li>"+
							subjects[i].title+"<br />"+
							"<img src=\""+subjects[i].images.large+"\" >"+
							"</li>");
						}
					});
				}
			}
		</script>
</body>
</html>

2.CORS

  • CORS 是什么? CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get 和post 请求。跨域资源共享标准新增了一组HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
  • CORS 怎么工作的? CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。
  • CORS 的使用 主要是服务器端的设置:
router.get("/testAJAX" , function (req , res) {
	//通过res 来设置响应头,来允许跨域请求
	//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
	res.set("Access-Control-Allow-Origin","*");
	res.send("testAJAX 返回的响应");
});