1 后端基础ajax
1.1 URL
- 互联网资源都有一个URL:
- 统一资源定位符 uniform resouce locator
- 资源:网页,图片,视频,程序,链接…
- htttp://www.baidu.com/phone?name=‘wangcai’&age=100
- 协议:http://
- IP地址/域名:baidu.com , www仅仅是前缀
- baidu.com ,一级域名(我们买的就是这个)
- www.baidu.com ,二级域名 ,(自己配的)
- news.baidu.com ,二级域名
- music.baidu.com ,二级域名
- yule.news.baidu.com ,三级域名
- 路径名:/xx/yy/mm
- 查询字符串:?开头 ,给服务器传递的数据 ,get传参
- 请求服务器方式,
- get
- post
- 服务器渲染
- 前端值需要开发好前端页面,把页面给后端,后端程序员根据模板引擎把模板中的假数据换成真实的数据,渲染给浏览器,浏览器得到的是已经渲染好的页面。
- 客户端渲染
- ajax给服务器要数据,拿到数据,在客户端进行渲染
2 ajax
- Asynchronous Javascript And XML(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。
- 几种ajax
- 原生ajax
- jQuery中的ajax
- 新时代的ajax
- fetch:不是对原生ajax封装,是一种新的数据请求的方案,是一种新的技术
- axios:也是对 ajax的封装,在vue和react中的都是axios
- 反向ajax:正向的是ajax先请求,后给出响应,反向ajax就是服务器可以主动推送数据给客户端
- http协议:客户端先发出响应,服务器给出响应
- socket协议:让服务器给出响应
2.1 认识ajax
-
不是一门新的技术 一堆的老技术拼到一起的
-
核心:构造器 XMLHTTPRequest
-
let xhr = new XMLHttpRequest();
2.2 实现原生ajax的五个步骤
- 创建XMLHttpRequest异步对象
- 设置回调函数
- 使用open方法与服务器建立连接
- 向服务器发送数据
- 在回调函数中针对不同的响应状态进行处理
****************************************************************
// 1-创建XMLHttpRequest异步对象
var xhr;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xhr=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
****************************************************************
// 2- 设置回调函数
xhr.onreadystatechange = callback
****************************************************************
// 3- 使用open方法与服务器建立连接
// get 方式
xhr.open("get", "test.php", true)
// post 方式发送数据 需要设置请求头
xhr.open("post", "test.php", true)
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
****************************************************************
// 4- 向服务器发送数据
// get 不需要传递参数
xhr.send(null)
// post 需要传递参数
xhr.send("name=jay&age=18"
****************************************************************
// 5- 在回调函数中针对不同的响应状态进行处理
function callback() {
// 判断异步对象的状态
if(xhr.readyState == 4) {
// 判断交互是否成功
if(xhr.status == 200) {
// 获取服务器响应的数据
var res = xhr.responseText
// 解析数据
res = JSON.parse(res)
}
}
}
****************************************************************
属性 | 描述 |
---|---|
onreadystatechange | 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。 |
readyState | 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。 |
- | 0: 请求未初始化 |
- | 1: 服务器连接已建立 |
- | 2: 请求已接收 |
- | 3: 请求处理中 |
- | 4: 请求已完成,且响应已就绪 |
status | 200: “OK” 404: 未找到页面 |
// 第一步, 创建ajax对象
let xhr = new XMLHttpRequest();
// 第二步,和服务器建立连接
xhr.open('get','/check?username=' + username);
// 第三步,发起请求,null表示请求体为空,post请求请求体不为空
xhr.send(null);
// 第四步,得到得到返回结果
// 状态发生改变的时候自动调用onreadystatechange
xhr.onreadystatechange = function() {
/**
* xhr中有一个readyState用于记录ajax请求状态
* 第一步 状态为0
* 第二步 状态为1
* 第三步 状态为2
* 状态为4,表示ajax获取到数据
*/
if(xhr.readyState == 4 && xhr.status == 200) {
// xhr.responseText 记录响应结果
console.log(xhr.responseText);
}
2.3 ajax的几个状态
- 0:xhr对象创建完毕,状态就是0
- 1:调用open方法,设置了请求连接
- 2:xhr已经接收到数据了,接收到数据都是需要解析的
- 浏览器发请求,服务器把数据响应给浏览器,浏览器拿到数据,用完后四需要解析的
- 3:正在解析数据(我们想要的数据,必须等到解析完毕)
- 4:数据解析完成
2.4 对数据编码进行处理
- 当我们输入中文时,浏览器会帮我们编码
/**
* 当user.value值为中文时,浏览器自动编码
* 如果我们输入admin&age=110,浏览器会把&age=110识别为参数,因此需要我们进行编码
*/
// let username = user.value; //会出问题
let username = encodeURIComponent(user.value);
2.5 API接口
- 当服务器给客户端返回一个JSON字符串数据,此时这个路由有了一个别名,叫API接口。
- API接口是后端程序员提供,前端程序员使用,通过ajax调用api接口。
2.5.1 接口文档
接口文档包含的几个部分:
接口文档可以包含很多信息,也可以按需进行精简,不过,一个合格的接口文档,应该包含以下6项内容,从而为接口的调用
- 接口名称:用来标识各个接口的简单说明,如登录接口,获取图书列表接口等。
- 接口URL:接口的调用地址。
- 调用方式:接口的调用方式,如GET 或 POST。
- 参数格式:接口需要传递的参数,每个参数必须包含参数名称、参数类型、是否必选、参数说明这四项内容。
- 响应格式:接口的返回值的详细描述,一般包含数据名称。数据类型、说明3项内容。
- 返回示例(可选):通过对象的形式,例举服务器返回数据的结构。
示例:http://127.0.0.1:3000/check
接口名称:检测用户名是否存在
接口URL:http://127.0.0.1:3000/check
调用方式:post
参数格式:username=‘123’
响应格式:{“code”:1,“msg”:“恭喜你,该用户名可以使用…”}
返回示例(可选):{“code”:1,“msg”:“恭喜你,该用户名可以使用…”}
2.5.2 接口测试
Postman软件
2.5.3 编写接口文档
3 jQuery中的ajax
-
$.get(url,[data],[fn],[type]) String,Map,Function,String
-
$.post(url,[data],[fn],[type]) String,Map,Function,String
url:待载入页面的URL地址
data:待发送 Key/value 参数。
callback:载入成功时回调函数。
type:返回内容格式,xml, html, script, json, text, _default。
- $.ajax(url,[settings])
// get请求
// $('#username').on('blur',function() {
// let username = $(this).val();
// $.get('/check',{username}, res=>{
// $('#msg').html(res.msg)
// },'json')
// })
// post请求
// $('#username').on('blur',function() {
// let username = $(this).val();
// $.post('/check',{username}, res=>{
// $('#msg').html(res.msg)
// },'json')
// })
// $.ajax
$('#username').on('blur', function () {
let username = $(this).val();
$.ajax({
url: 'check',
type: 'get',
data: { username },
success(res) {
$('#msg').html(res.msg);
console.log(res);
},
error(err) {
console.log(err);
}
})
})
4 跨域问题
- 产生跨域问题的条件
- 使用ajax请求服务器
- 不同域的请求
- 跨域问题只会产生在浏览器端,Android,iOS,没有跨域问题
- 同源策略目的:安全,保护数据
4.1同源策略
4.1.1 源的定义
如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。
-
不同的域
- 协议,如http/https
- 主机,有域名和IP两种,如www.baidu.com,127.0.0.1
- 端口,如80,8080
-
如果协议,主机,端口完全一致表示同一个域,只要有一个不同,就认为是不同域
4.1.2同源策略是什么
-
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。
-
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
4.1.3不受同源策略限制的
-
页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
-
跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="…">,<img>,<link>,<iframe>等。
4.2 解决跨域问题
4.2.1 CORS
- 两种方式:
- 自己配置
- 引用第三方插件
- 跨域资源共享Cross-origin resource sharing
- 实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
4.2.1.1 自己配置
// 3000端口的页面访问4000端口
$('#btn').click(function () {
$.get('http://127.0.0.1:4000/ajax', res => {
console.log(res)
})
})
// 服务端配置,需要写在路由之前
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:3000"); // 允许http://127.0.0.1:3000访问
res.setHeader("Access-Control-Allow-Credentials", true); // 允许携带cookie
res.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
next();
})
********************************************************
app.get('/ajax', (req, res) => {
res.send({ code: 0, msg: '4000端口的数据' });
})
app.listen(4000, () => {
console.log('Server is runing in 4000...')
})
4.2.1.2 使用第三方插件
// 安装
npm install cors
// 引入
var cors = require('cors')
// 挂载
app.use(cors())
4.2.2代理
4.2.2.1 自己写
原理:代理(node服务器)与服务器之间没有跨域问题
let url = 'http://www.weather.com.cn/data/cityinfo/101010100.html'; // 天气接口
$('#btn').click(function () {
// 直接访问,出现跨域问题
// $.get('http://www.weather.com.cn/data/cityinfo/101010100.html', res => {
// console.log(res)
// }, 'json')
// 使用代理
// 将天气接口以请求参数方式传给node服务器,让服务器请求资源,并将资源返回ajax
$.get('/proxy', { url }, res => {
console.log(res)
}, 'json')
//拿到数据
// "weatherinfo": {
// "city": "北京",
// "cityid": "101010100",
// "temp1": "18℃",
// "temp2": "31℃",
// "weather": "多云转阴",
// "img1": "n1.gif",
// "img2": "d2.gif",
// "ptime": "18:00"
// }
})
// 服务器端配置proxy请求
// 1.引入http模块
let http = require('http');
// 2.处理请求
app.get('/proxy', (req, res) => {
let url = req.query.url;
http.get(url, (response) => {
let data = "";
response.on('data', (chunk) => {
data += chunk;
})
response.on('end', () => {
res.json(data);
})
})
})
4.2.2.2 安装浏览器插件
- Access-Control-Allow-Origin
4.2.3 JSONP(重点)
- 本质不是ajax,本质是script标签发出的请求
- 原理:其本质是利用了标签具有可跨域的特性,由服务端返回预先定义好的javascript函数的调用,并且将服务端数据以该函数参数的形式传递过来
4.2.3.1 原理分析
// 原理,客户端
/**
* 首先定义一个函数f,这个函数f 就是用来接收跨域数据的
* 当点击按钮时,创建一个script标签,并且在script标签中添加src属性,
* src中的内容是要跨域访问的资源,src格式为 /jsonp?callback=f',src中有一个参数callback=f
* 在服务器端通过req.query.callback 获取到f,并从服务器返回一个 f+('res'),
* 返回的结果是f('res'), 在客户端有函数f(),所以浏览器回去执行这个函数,此时函数的参数就是要得到的跨域数据
* 由于script不存在跨域问题,当浏览器加载到新创建的script标签时,就会加载src,
*
*/
$('button').click(function() {
createScript('http://127.0.0.1:3000/jsonp?callback=f');
})
// 预先定义好的函数,让服务器调用这个函数
function f(res) {
console.log(res)
// alert(res);
}
// 创建一个script标签,script标签不存在跨域问题,通过标签引用资源
function createScript(src) {
let script = document.createElement('script');
script.src = src;
document.body.appendChild(script);
}
// 服务端,通过req.query拿到函数名,将数据以函数参数的形式进行保存,返回这个带参数的函数,浏览器会执行这个预先定义好的函数,从而实现数据的获取
app.get('/jsonp',(req,res)=> {
let cb = req.query.callback;
res.send(cb+'("hahahha JSON")');
})
4.2.3.1 jQuery中使用JSONP
// 'https://api.asilu.com/geo/' 这是一个JSONP接口
$('button').click(function() {
$.get('https://api.asilu.com/geo/',function(res) {
console.log(res)
},'jsonp')
})
4.2.4 Nginx
…