Ajax(Asynchronous JavaScript And XML)

通过ajax浏览器可以像服务器发送异步请求,最大的优势:可以在不刷新网页的情况下,异步的向后台发送请求,在前端接受并展示数据

本次学习所用到的插件

  1. Node.js
  2. NPM
  3. express(简单的web服务器)
  4. nodemon(用于自动重启node服务器)

XML

  1. XML是什么? 有什么用?

    1. XML 被设计用来传输和存储数据
    2. XML 的设计宗旨是传输数据(XML),而非显示数据(HTML)
    3. XML 被设计为具有自我描述性
    4. XML 标签没有被预定义。您需要自行定义标签
  2. 语法:

    <?xml version="1.0" encoding="utf-8">
    <root>
    <!-- 标签可以自由命名 -->
    <name>Fitz</name> <!-- 必须正确关闭标签 -->
    </root>
    <root>
    <!-- 属性必须加引号 -->
    <!-- 尽量不要使用属性 -->
    <name gender="male">Fitz</name>
    <address province="GD">HouJie</address>
    </root>
    <root>
    <!-- 这是错误的属性使用方法 -->
    <attr attr1="error" attr2="wrong">属性不应该这样用</attr>
    </root>
    <root>
    <!-- 特殊的符号应该使用实体 -->
    <sample>使用实体例如:大于号 &gt;</sample>
    </root>

JSON

由于JSON 比 XML 更小、更快,更易解析。所以现在AJAX返回的数据格式多是使用JSON

{
"name": "Fitz",
"hobby": "computer science",
"dream": "good at math"
}

关于AJAX

  1. ajax的优点

    1. 无需刷新页面即可与服务器进行通讯
    2. 允许根据用户事件来更新部分页面内容
  2. ajax的缺点
    1. 没有浏览历史,这就导致不能回退
    2. 存在跨域问题
    3. 对SEO不友好

HTTP协议

HTTP(hypertext transport protocol)超文本传输协议,规定了浏览器和万维网服务器之间互相通信的规则

  • 请求报文

    • 重要格式与参数
    行    ====>  GET/POST  /s?ie=utf-8  HTTP/1.1
    头 ====> Host: baidu.com
    Cookie: name=trash
    content-type: application/x-www-form-urlencoded
    user-Agent: chrome 83
    空行 ====>
    体 ====> username=root&password=root
  • 响应报文

  • 重要格式与参数

    行    ====>  HTTP/1.1  200  OK
    头 ====> Host: baidu.com
    content-type: text/html;charset=utf-8
    content-length: 2048
    空行 ====>
    体 ====> <html>
    <head></head>
    <body></body>
    </html>

AJAX重点之XMLHttpRequest对象

XMLHttpRequest对象作用是前端向服务端发送ajax请求,别接收来自服务端的数据

``` javascript {.line-numbers}
//主要步骤 // 1 创建xhr对象
var xhr = new XMLHttpRequest(); // 2 初始化 设置请求方法 与 URL
xhr.open('GET','http://127.0.0.1:8000/server'); // 3 发送请求
xhr.send(); // 4 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//处理结果
// console.log(`行 状态码===>${xhr.status}`);
// console.log(`行 状态字符串===>${xhr.statusText}`);
// console.log(`头===>${xhr.getAllResponseHeaders()}`);
// console.log(`体===>${xhr.response}`);
}else{
console.log('Some Error !');
}
}
```

关于 onreadystatechange与readyState

每当 readyState 改变时,就会触发 onreadystatechange 事件,readyState存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。

0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪

服务端 实例

使用插件 express

//引入express
const express = require("express"); //创建应用对象
const app = express(); //创建路由规则
app.get('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装 //设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.send('成功接收到来自服务端的消息');
}) app.post('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装 //设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.send('成功接收到来自服务端的消息 -post method');
}) app.listen(8000,()=>{
console.log('服务已经在8000端口启动....');
})

ajax-get 实例

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewpor" content="width=device-width initial-scale=1.0">
<title>Fitz</title> <style> * {
margin: 0;
padding: 0;
} #result{
width: 200px;
height: 100px;
border: solid 1px black;
} </style> </head>
<body>
<button>点击发送请求</button>
<div id="result"></div> <script>
//获取button
var btn = document.getElementsByTagName('button')[0];
var result = document.getElementById("result");
btn.onclick = function(){
//AJAX步骤 // 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 初始化 设置请求方法 与 URL
xhr.open('GET','http://127.0.0.1:8000/server?name=fitz');
// 3 发送请求
xhr.send();
// 4 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//处理结果
// console.log(`行 状态码===>${xhr.status}`);
// console.log(`行 状态字符串===>${xhr.statusText}`);
// console.log(`头===>${xhr.getAllResponseHeaders()}`);
// console.log(`体===>${xhr.response}`); //展示在前端div中
result.innerHTML = xhr.response;
}else{
console.log('Some Error !');
}
}
}
}
</script>
</body>
</html>

ajax-post 实例

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewpor" content="width=device-width initial-scale=1.0">
<title>Fitz</title> <style> * {
margin: 0;
padding: 0;
} #result{
width: 200px;
height: 100px;
border: solid 1px black;
} </style> </head>
<body>
<button>点击发送请求</button>
<div id="result"></div> <script>
//获取button
var btn = document.getElementsByTagName('button')[0];
var result = document.getElementById("result");
btn.onclick = function(){
//AJAX步骤 // 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 初始化 设置请求方法 与 URL
xhr.open('POST','http://127.0.0.1:8000/server');
// 3 发送请求
xhr.send('name=Fitz&gender=Male'); //post请求参数应在send方法中添加
// 4 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//处理结果
// console.log(`行 状态码===>${xhr.status}`);
// console.log(`行 状态字符串===>${xhr.statusText}`);
// console.log(`头===>${xhr.getAllResponseHeaders()}`);
// console.log(`体===>${xhr.response}`); //展示在前端div中
result.innerHTML = xhr.response;
}else{
console.log('Some Error !');
}
}
}
}
</script>
</body>
</html>

设置请求头信息

// 2  初始化   设置请求方法 与 URL
xhr.open('POST','http://127.0.0.1:8000/server');
//设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
// 3 发送请求
xhr.send('name=Fitz&gender=Male');

服务端响应JSON数据

方法一

前端代码

var div = document.getElementById('result');
window.onkeydown = function(){
//发送请求
var xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//方法一
//通过手动转换来响应JSON
let data = JSON.parse(xhr.response);
console.log(data);
div.innerHTML = data.username;
}
}
}
}

方法二

前端代码

var div = document.getElementById('result');
window.onkeydown = function(){
//发送请求
var xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
//方法二
//自动转换
console.log(xhr.response);
div.innerHTML = xhr.response.username;
}
}
}
}

后端代码

//引入express
const express = require("express");
const { json } = require("body-parser"); //创建应用对象
const app = express(); // //创建路由规则
app.all('/server',(request,response)=>{
//request 请求报文封装
//response 响应报文封装 //设置响应头
//允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.setHeader('Access-Control-Allow-Header','*') //要发送回去前端的数据
const data = {
username: 'root',
password: 'root123'
} const data2str = JSON.stringify(data); //手动将data对象转换为JSON字符串
response.send(data2str); //send方法只能接收一个字符串
}) app.listen(8000,()=>{
console.log('服务已经在8000端口启动....');
})

AJAX关于在IE中的缓存问题

解决方法:使用时间戳以保证每次的URL都不一样(参数不一样)

var xhr = new XMLHttpRequest();
xhr.open("GET",'http://127.0.0.1:8000/ie?t'+Date.now()); //使用时间戳
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}

超时设置、回调与网络异常的回调

var xhr = new XMLHttpRequest();
//设置超时
xhr.timeout = 2000;
//设置超时回调
xhr.ontimeout = function(){
console.log('你的网络似乎有些慢');
}
//设置断网回调
xhr.onerror = function(){
console.log('你的网络似乎有些问题');
}
xhr.open("GET",'http://127.0.0.1:8000/cancel); //使用时间戳
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}

取消ajax请求

var btn = document.getElementById('btn');
var btn2 = document.getElementById('btn2');
var div = document.getElementById('result'); var xhr = null; addEventListener('click',function(){
if(xhr){
xhr.abort();
}
xhr = new XMLHttpRequest();
xhr.open("GET",'http://127.0.0.1:8000/cancel');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if (xhr.status >= 200 && xhr.status < 300){
div.innerHTML = xhr.response; //把结果在前端显示
}
}
}
}) btn2.onclick = function(){
xhr.abort();
}

jquery发送ajax请求

$(function(){
//get
$('button').eq(0).click(function(){
$.get('http://127.0.0.1:8000/jquery',
{
name: 'fitz',
age: 20
},
function(data){
console.log(data);
},'json')
}) //post
$('button').eq(1).click(function(){
$.post('http://127.0.0.1:8000/jquery',
{
name: 'fitz',
age: 20
},
function(data){
console.log(data);
})
}) //通用方法
$('button').eq(2).click(function(){
$.ajax({
//url
url: 'http://127.0.0.1:8000/jquery',
//要发送的参数
data: {
a: 'a',
b: 'b'
},
//ajax请求类型
type: 'GET',
//指定响应体的类型
dataType: 'json',
//设置超时时间
timeout: 2000,
//成功的回调
success: function(data){
console.log(data);
},
//失败的回调
error: function(e){
console.log(e);
},
//设置头部信息
headers: {
a: 200
}
})
})

fetch函数发送ajax请求

fetch('http://127.0.0.1:8000/fetch?test=ok',
{
//请求方法
method: 'POST',
//请求头
headers: {
name: 'Da'
},
//请求体
body: 'username=tri4123'
}).then((response)=>{
console.log(response);
return response.text();
//可以自动解析响应体为JSON格式的数据
// return response.json();
}).then((response=>{
console.log(response);
})
);

跨域

同源策略:协议、域名、端口号 必须完全相同

违背同源策略的称之为跨域

解决跨域

使用具备跨域特性的标签:<img> <script> <link> <iframe>

  1. 使用jsonp:在前段定义处理函数,供后端调用

    前端代码

    //在前段设置处理函数,供后端调用
    <script>
    //处理数据的函数
    function handleData(data){
    //获取result元素
    var result = document.getElementById('result');
    result.innerHTML = data.name;
    }
    </script> <!-- <script src="./jsonp.js"></script> -->
    <script src="http://127.0.0.1:8000/jsonp-server"></script>

    后端代码

    const express = require("express");
    const app = express();
    app.all('/jsonp-server',(request,response)=>{
    var PersonInfo = {
    name: 'Lx'
    } //调用前端已经定义好的函数
    //就能将后端数据跨域传给前端
    response.end(`handleData(${JSON.stringify(PersonInfo)})`)
    // response.send('console.log("jsonp实验成功")')
    })
  2. jquery(原理还是jsonp)

    前端代码


    //callback=? 参数是必须的,这会在前端注册一个函数 供后端调用
    $.getJSON('http://127.0.0.1:8000/server?callback=?',function(){
    //后端的数据....
    })

    后端代码

    const express = require("express");
    const app = express();
    app.all('/server',(request,response)=>{
    var PersonInfo = {
    name: 'Lx'
    } //获取在前端注册的callback函数
    var callbackFunc = request.query.callback; //调用前端已经定义好的函数
    //就能将后端数据跨域传给前端
    response.end(`${callbackFunc}(${JSON.stringify(PersonInfo)})`);
    })
  3. CORS 跨域资源共享 官方的跨域方案

CORS通过在服务端设置一个响应头告诉前端,该请求是否允许跨域,浏览器收到响应头后会对响应进行放行

后端代码

//允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Access-Control-Allow-Headers','*');
response.setHeader('Access-Control-Allow-Methods','*');

看完我的笔记不懂也会懂----Ajax的更多相关文章

  1. 看完我的笔记不懂也会懂----bootstrap

    目录 Bootstrap笔记 知识点扫盲 容器 栅格系统 源码分析部分 外部容器 栅格系统(盒模型)设计的精妙之处 Bootstrap笔记 写在开始: 由于我对AngulaJS的学习只是一个最浅显的过 ...

  2. 看完我的笔记不懂也会懂----AngulaJS

    目录 Angular.js学习笔记 ng-app(指令) ng-model ng-init angular之表达式 双向数据绑定 数据流向的总结 作用域对象 控制器对象 依赖对象与依赖注入 命令式与声 ...

  3. 看完我的笔记不懂也会懂----git

    Git学习笔记 - 什么是Git - 首次使用Git - DOS常用命令 - Git常用命令 - 关于HEAD - 版本回退 - 工作区.暂存区与版本库 - git追踪的是修改而非文件本身 - 撤销修 ...

  4. 看完我的笔记不懂也会懂----Node.js

    Node.js 学习 - 命令行窗口 - 进程与线程 - ECMAScript的缺点 - Node模块化 - Node中的全局对象 - 包 package - NPM包管理器 (Node Packag ...

  5. 看完我的笔记不懂也会懂----javascript模块化

    JavaScript模块化 模块化引子 模块化的历史进化 模块化规范 CommonJS规范 Node.js(服务器端) 下项目的结构分析 browerify(浏览器端) 下项目的结构分析 AMD规范 ...

  6. 看完我的笔记不懂也会懂----less

    目录 Less学习 语法篇 注释 变量 映射(Maps) @规则嵌套和冒泡 less中的嵌套规则 less中的混合 less的运算 extend延伸/继承 less忽略编译(转义) 导入(Import ...

  7. 看完我的笔记不懂也会懂----MongoDB

    MongoDb数据库学习 - 数据库的分类 - 数据库基本概念 - MongoDB常用指令 - MongoDB的CURD - sort({key:*[1,-1]}).limit(num).skip(n ...

  8. 看完我的笔记不懂也会懂----MarkDown使用指南

    目录 语法 [TOC] 自动生成目录 1. 标题 2. 文本强调 3. 列表 4. 图片 5. 超链接 6. 文本引用 7. 分割线 8. 代码 9. 任务列表 (MPE专属) 10. 表格 11. ...

  9. 看完我的笔记不懂也会懂----ECMAscript 567

    目录 ECMAscript 567 严格模式 字符串扩展 数值的扩展 Object对象方法扩展 数组的扩展 数组方法的扩展 bind.call.apply用法详解 let const 变量的解构赋值 ...

随机推荐

  1. Luogu T16048 会议选址

    本题idea版权来自CSDN博客Steve_Junior的医院设置2. 并没有什么用的链接 题目背景 \(A\)国的国情十分独特.它总共有\(n\)个城市,由\(n-1\)条道路连接.国内的城市当然是 ...

  2. hdu 4521 小明系列问题——小明序列 线段树

    题意: 给你一个长度为n的序列v,你需要输出最长上升子序列,且要保证你选的两个相邻元素之间在原数组中的位置之差大于d 题解: 这个就是原来求最长上升子序列的加强版,这个思路和最长上升子序列的差不多   ...

  3. codeforces626D . Jerry's Protest (概率)

    Andrew and Jerry are playing a game with Harry as the scorekeeper. The game consists of three rounds ...

  4. Codeforces Round #681 (Div. 1, based on VK Cup 2019-2020 - Final) B. Identify the Operations (模拟,双向链表)

    题意:给你一组不重复的序列\(a\),每次可以选择一个数删除它左边或右边的一个数,并将选择的数append到数组\(b\)中,现在给你数组\(b\),问有多少种方案数得到\(b\). 题解:我们可以记 ...

  5. Codeforces Round #669 (Div. 2) B. Big Vova (枚举)

    题意:有一个长度为\(n\)的序列,你需要对其重新排序,构造一个新数组\(c\),\(c_{i}=gcd(a_{1},...,a{i})\)并且使得\(c\)的字典序最小. 题解:直接跑\(n\)次, ...

  6. Codeforces Round #667 (Div. 3) C. Yet Another Array Restoration (数学)

    题意:给你两个数字\(x\)和\(y\),让你构造一个长度为\(n\)的序列,要求包含\(x\)和\(y\),并且排序后相邻两项的差值相等. 题解:有排序后相邻两项的差值相等可知,构造的序列排序后一定 ...

  7. java实现定时任务解决方案

    在线corn表达式 1. 总结常见的实现定时任务的几种方法 thread实现 [原理:通过创建一个线程,让他在while循环里面一直运行,用sleep() 方法让其休眠从而达到定时任务的效果.] Ti ...

  8. 1、Django框架目录介绍

    1.windows上安装django pip install django==1.10.3 安装完成后:django-admin.exe 默认存放路径:C:\Users\licl11092\AppDa ...

  9. C++中overload 、override、overwrite 之间的区别

    Overload(重载):在C++程序中,可以将语义.功能相似的几个函数用同一个名字表示,但参数或返回值不同(包括类型.顺序不同),即函数重载.(1)相同的范围(在同一个类中):(2)函数名字相同:( ...

  10. 攻防世界-Web-lottery(.git泄露、php源码审计、弱类型利用)

    扫描目录,发现.git泄露: 提取.git泄露的源码,得到许多文件: 网站这里: 这就要审计一下代码,找找漏洞了. 经过一番审计,猜数字对应的函数在api.php中: 我们要绕过这个$win_numb ...