前端工程化17-邂逅原生的ajax、跨域、JSONP

5、邂逅原生的ajax

5.1、什么是ajax

AJAX 全称为Asynchronous Javascript And XML,就是异步的 JS 和 XML。通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:页面无刷新获取数据。AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。

5.2、XML简介

XML 可扩展标记语言。

XML 被设计用来传输和存储数据。

XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据。

用XML表示一个学生数据:

<student><name>孙悟空</name><age>18</age><gender></gender>
</student>

现在已经被JSON取代了。

{"name":"孙悟空","age":18,"gender":"男"}

但是还有一些老系统在用这种数据交换格式,因为替换的成本实在太大,不能接受

5.3、ajax的优点

可以无需刷新页面而与服务器端进行通信。

允许你根据用户事件来更新部分页面内容。

5.4、AJAX的缺点

没有浏览历史,不能回退;固有问题

存在跨域问题;可以解决

SEO不友好; 没有意义,有竞价排名这个东西

5.5、AJAX核心对象

XMLHttpRequest,AJAX的所有操作都是通过该对象进行的。

函数、函数对象、方法

5.6、搭建测试ajax请求的服务器

创建项目(变成一个符合npm规范的包)

​ npm init

​ yarn inti

规定项目名称(不能有大写字母,也不能有数字开头)

​ ajax_0826

​ 一路回车

安装express

​ yarn add express

新建一个server.js文件

​ 下带附件

启动服务器

​ node server.js

​ 右键 Code Runner插件

​ 推荐敲命令,后期我们脚手架里都是敲命令

热启动node服务

​ nodemon server.js

服务器附件文件

//引入express
const express = require('express')
const cors = require('cors')//创建app实例对象
const app = express()
//使用中间件解析urlencoded编码形式的请求体参数
app.use(express.urlencoded({extended:true}))
//使用中间件解析json编码形式的请求体参数
app.use(express.json())
app.use(cors())//暴露静态资源
app.use(express.static(__dirname+'/src'))//响应GET请求--可以接收query参数
app.get('/test_get',(request,response)=>{console.log('有人请求test_get了--携带的query参数是:',request.query);/* response.setHeader('Access-Control-Allow-Origin','*')response.setHeader('Access-Control-Expose-Headers','*') */response.send('hello_test_get')
})//响应GET请求--可以接收params参数
app.get('/test_get2/:name/:age',(request,response)=>{console.log('有人请求test_get2了--携带的params参数是:',request.params);response.send('hello_test_get2')
})//响应get请求
app.get('/get_person',(request,response)=>{console.log('有人请求get_person了');const person = {name:'tom',age:18,sex:'女'}response.send(JSON.stringify(person))
})//响应get请求
app.get('/get_person_delay',(request,response)=>{console.log('有人请求get_person了');const person = {name:'tom',age:18,sex:'女'}setTimeout(()=>{response.send(JSON.stringify(person))},3000)
})//响应POST请求--可以接收请求体参数
app.post('/test_post',(request,response)=>{console.log('有人请求test_post了--携带的请求体参数是',request.body);response.send('hello_test_post')
})//响应get请求---jquery
app.get('/test_jquery_get',(request,response)=>{console.log('有人请求test_jquery_get了',request.query);const car = {name:'马自达·阿特兹',price:'25万'}response.send(JSON.stringify(car))
})//响应post请求----jquery
app.post('/test_jquery_post',(request,response)=>{console.log('有人请求test_jquery_post了',request.body);const car = {name:'马自达·阿特兹',price:'25万'}response.send(JSON.stringify(car))
})/* app.options('/test_put',(request,response)=>{response.setHeader('Access-Control-Allow-Origin','*')response.setHeader('Access-Control-Expose-Headers','*')response.setHeader('Access-Control-Allow-Methods','*')response.send()
}) */app.put('/test_put',(request,response)=>{
/* 	response.setHeader('Access-Control-Allow-Origin','*')response.setHeader('Access-Control-Expose-Headers','*') */response.send('hello_test_put')
})app.get('/test_jsonp',(request,response)=>{const {callback} = request.queryconsole.log(callback);const person = [{name:'tom',age:18},{name:'老刘',age:5}]response.send(`${callback}(${JSON.stringify(person)})`)
})//监听
app.listen(8080,(err)=>{if(!err) {console.log('测试ajax请求的服务器开启成功了!测试地址如下');console.log('http://127.0.0.1:8080/1_ajax小试牛刀.html');console.log('http://127.0.0.1:8080/2_xhr的5种状态.html');console.log('http://127.0.0.1:8080/3_ajax_get请求.html');console.log('http://127.0.0.1:8080/4_ajax_post请求.html');console.log('http://127.0.0.1:8080/5_ajax_解析json数据.html');console.log('http://127.0.0.1:8080/6_ajax_处理IE浏览器get请求缓存问题.html');console.log('http://127.0.0.1:8080/7_ajax请求的异常与超时处理.html');console.log('http://127.0.0.1:8080/8_ajax取消请求.html');console.log('http://127.0.0.1:8080/9_避免多次重复请求.html');console.log('http://127.0.0.1:8080/10_jquery封装的ajax.html');console.log('http://127.0.0.1:8080/11_演示回调地狱.html');}
})

5.6、如何使用AJAX的核心对象

//1.创建XMLHttpRequest实例对象
const xhr = new XMLHttpRequest()
//2.设置请求信息
xhr.open(method,url) //配置请求
xhr.setRequestHeader(key,value)//设置请求头(可选)
//3.发送请求
xhr.send(body) //get请求不传body参数,只有post请求使用
//4.接收响应
xhr.onreadystatechange = ()=>{if(xhr.readyState === 4 && xhr.status === 200 ){console.log(xhr.response)}
}

5.7、解决IE缓存问题

问题:在一些浏览器中(IE),由于缓存机制的存在,ajax只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。

解决方式:浏览器的ajax缓存是根据url地址来记录的,所以我们只需要修改url地址即可避免缓存问题

xhr.open('get','url/t='+Date.now())
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>6_ajax_处理IE-get请求缓存问题</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:ajax_处理IE-get请求缓存问题</h3><button id="btn">点我发送请求(原生js-ajax-get)</button><div id="content"></div><script type="text/javascript" >const btn = document.getElementById('btn')const content = document.getElementById('content')btn.onclick = function(){//实例xhrconst xhr = new XMLHttpRequest()//绑定监听xhr.onreadystatechange = function(){if(xhr.readyState === 4){if(xhr.status >= 200 && xhr.status <300){console.log(xhr.response);}}}//配置请求xhr.open('GET','http://127.0.0.1:8080/get_person?t='+Date.now())//responseType用于指定返回数据的格式xhr.responseType = 'json'//发送请求xhr.send()}</script></body>
</html>

强缓存、协商缓存

浏览器禁用缓存 Disable cache

按住shift,点刷新,或者shift+f5,强制刷新后,点击获取数据。发现数据http请求状态码为304,证明本次请求走了协商缓存

关闭浏览器,关闭服务器,从新打开浏览器服务器

第一次请求状态码为200,数据成功回来,第二次请求状态码为200,第三次状态码为304,这是因为浏览器发现地址栏信息并没有发送对应的改变,,他会去问下服务器,你的数据是否发生了变化,服务器发现没变,给个304 你小子走协商缓存就好了,协商缓存终归还是给服务器发送了请求

IE这个东西就非常的武断,地址没变直接就会走缓存

5.8、AJAX请求状态

xhr.readyState 可以用来查看请求当前的状态

  • 0: 表示XMLHttpRequest实例已经生成,但open未调用。

  • 1: open已调用,但send还未调用,此时仍然可以修改请求头信息。

  • 2: 表示send()方法已经执行,并且头信息和状态码已经收到。

  • 3: 表示正在接收服务器传来的部分数据。

  • 4:表示数据已经接收完毕

5.9、原生AJAX小试牛刀

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>1_ajax小试牛刀</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:ajax小试牛刀</h3><button id="btn">点我发送请求(原生js-ajax-get)</button><div id="content"></div><script type="text/javascript" >//获取按钮const btn = document.getElementById('btn')const content = document.getElementById('content')//给按钮绑定监听btn.onclick = ()=>{//1.创建xhr实例对象const xhr = new XMLHttpRequest()//on  当xxx时候//ready 准备//state 状态//change 状态//xhr内部有5种状态,值分别为:0、1、2、3、4//xhr实例对象,在实例出来的那一刻状态就是0xhr.onreadystatechange = ()=>{if(xhr.readyState === 4){console.log(xhr.response);content.innerHTML = `<h3>${xhr.response}</h3>`}}//2.指定发送请求的:method、urlxhr.open('GET','http://127.0.0.1:8080/test_get')//3.发送请求xhr.send()}</script></body>
</html>

5.1、xhr的5种状态

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>2_xhr的5种状态</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:xhr的5种状态</h3><button id="btn">点我发送请求(原生js-ajax-get)</button><div id="content"></div><script type="text/javascript" >//获取按钮const btn = document.getElementById('btn')const content = document.getElementById('content')//给按钮绑定监听btn.onclick = ()=>{//1.创建xhr实例对象const xhr = new XMLHttpRequest()//xhr实例对象,在实例出来的那一刻状态就是0/* xhr内部有5种状态,值分别为:0、1、2、3、40:实例出来的那一刻状态就是0,初始状态。1:open已经调用了,但是send还没有调用,此时可以修改请求头内容。2:send已经调用了,已经无法修改请求头3:已经回来一部分数据了,小的数据会在此阶段一次性接收完毕,较大的数据有待进一步接收,响应头回来了。4:数据全部接收完毕*/xhr.onreadystatechange = ()=>{/* if(xhr.readyState === 1){xhr.setRequestHeader('demo',123) //配置请求头} *//* if(xhr.readyState === 2){xhr.setRequestHeader('demo',123) //配置请求头--报错} */if(xhr.readyState === 3){console.log('3时接收到的数据',xhr.response);console.log('3时接收到的响应头',xhr.getAllResponseHeaders());}if(xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)){console.log(xhr.response);content.innerHTML = `<h3>${xhr.response}</h3>`}}//2.指定发送请求的:method、urlxhr.open('GET','http://127.0.0.1:8080/test_get')//3.发送请求xhr.send()}</script></body>
</html>

5.2、ajax的get请求

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>3_ajax_get请求</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:ajax_get请求</h3><button id="btn">点我发送请求(原生js-ajax-get)</button><div id="content"></div><script type="text/javascript" >//获取按钮const btn = document.getElementById('btn')const content = document.getElementById('content')//给按钮绑定监听btn.onclick = ()=>{//1.创建xhr实例对象const xhr = new XMLHttpRequest()//绑定监听xhr.onreadystatechange = ()=>{if(xhr.readyState === 4 ){if(xhr.status >= 200 && xhr.status < 300){console.log(xhr.response);content.innerHTML = `<h3>${xhr.response}</h3>`}}}//#region /* 1.形如:key=value&key=value 就是query参数的urlencoded编码形式2.形如:/xx/xxx/老刘/18 就是params参数*///#endregion//2.指定发送请求的:method、url、参数// xhr.open('GET','http://127.0.0.1:8080/test_get?name=老刘&age=18') //携带query参数xhr.open('PUT','http://127.0.0.1:8080/test_put') //携带params参数//3.发送请求xhr.send()}</script></body><!-- get请求 1、query参数key=value&key=value 就是query参数的urlencoded编码形式2、params参数 /xx/xxx/老刘/18 就是params参数 这里有个小疑问?都是路径上的拼接我怎么知道他是地址的拼接还是参数一般来说在服务器有特殊的写法例如node服务器后端接口的写法/getList/:name/:age.例如SpringBoot后端接口的写法@PathVariable("name") String name在vue路由传参的写法上也有对应的params传参例如 {path: '/search/:words', component: Search} 他是有点类似于node服务器的写法	3、vscode折叠#region							-->
</html>

5.3、ajax的post请求

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>4_ajax_post请求</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:ajax_post请求</h3><button id="btn">点我发送请求(原生js-ajax-post)</button><div id="content"></div><script type="text/javascript" >//获取按钮const btn = document.getElementById('btn')const content = document.getElementById('content')//给按钮绑定监听btn.onclick = ()=>{//1.创建xhr实例对象const xhr = new XMLHttpRequest()//绑定监听xhr.onreadystatechange = ()=>{if(xhr.readyState === 4 ){if(xhr.status >= 200 && xhr.status < 300){console.log(xhr.response);content.innerHTML = `<h3>${xhr.response}</h3>`}}}//2.指定发送请求的:method、url、参数xhr.open('POST','http://127.0.0.1:8080/test_post')//追加响应头用于标识携带请求体参数的编码形式--urlencodedxhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')//追加响应头用于标识携带请求体参数的编码形式--json//xhr.setRequestHeader('Content-type','application/json')//3.发送请求const person = {name:'老刘',age:20}xhr.send('name=老刘&age=18') //携带urlencoded编码形式的请求体参数// xhr.send(JSON.stringify(person)) //携带json编码形式的请求体参数}</script></body>
</html>
<!-- 我们在上一个案例中、介绍到get请求可以携带query 和params参数、那么在post请求中都可以带什么参数呢?在我们一般的认知概念中、post请求带的是请求体参数、其实不是的他既可以携带query和parmas,但是一般我们都是放到请求体里post请求1、query2、parmas参数3、body参数放到send里边就是请求体参数、携带的是urlencoded编码形式的请求体参数当然我们也可以携带json编码形式的请求体参数注意必须携带请求头xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')xhr.setRequestHeader('Content-type','application/json')4、题外话	联想我们后端的技术我们发现后端接口在接收数据的时候,有的时候他用了注解有时候没有用,这是因为编码形式的不同,一种是urlencoded 一种是json格式的,一般如果前端发送json格式那么我们后端就需要用注解
-->

5.4、复习git操作

接下来我们需要回顾下怎么操作git,在接触Es6之前,我们已经系统的学习过了如何操作git,当你电脑上已经安装git客户端,你可以通过cmd黑窗口进行git操作,windows10操作系统也有一个工具 Windows PowerShell ,也可以通过git客户端自带的两种工具一个是GIT GUI Here、GIT Bash Here,cmd黑窗口的兼容性比较好,因为他从xp那个年代他就存在了,比如看看C盘下都有什么文件,使用命令dir,那我可以在cmd里敲Linux命令嘛?不好意思这是不支持的的,那谁支持呢?windows10的PowerShell是支持的,这个东西最大的优势是原始的Windows的shell脚本支持,Linux的也支持,这个东西我们用的不是很多,因为这个东西有的时候全局安装一个东西他就中断了,他说你没有权限去访问,用的多的还是cmd,GitBashHere就可以理解为一个是一个赠品。都可以,但是最好不要在PowerShell里敲了,有的时候全局安装东西容易出现问题,我那选择的使用方式是另一款软件Open Terminur here,他是一个单独的软件,他的劣势是启动速度比较慢,优势在于非常的美观,可以像浏览器一样开多个标签页,也可以调试那个字体颜色大小。

一般我们新到公司了,人家肯定会给你git地址,我们使用git clone 地址克隆下来,进入到桌面怎么进?桌面叫做Desktop 使用命令 cd des 按下tab他就联想了mkdir test,git clone 克隆一个仓库, 存在一个依赖管理文件,npm的话就是npm i,yarn的话就直接安装所有依赖,接下来就是git pull origin master,拉取写代码,add 添加到暂存区,git commit -m ‘update’ git push推送代码,在使用git项目管理项目时候,最大问题就是在处理冲突,分支的合并

5.5、VsCode怎么操作git

冲突就是同一行位置上产生了不同的内容就是冲突

image-20241001160908342

更改移动到右边这是不对的,右箭头是还原块的意思,+号箭头是暂存块

左侧工具栏更改旁边有一个+好,可以把所有更改的文件添加到暂存区,跟 git add .效果一样

暂存的更改旁边有一个减号意思是从暂存区域给他撤回来

消息输入框、可以输入对应的提交信息,跟 git -m “提交了一个文件”,此时只是我们本地仓库管理了对应文件

在往上走一点有三个点,点击,会显示拉取 推送、克隆、提交、更改、拉取、推送等选项操作

常用的几个命令

clone init add commit push pull

5.6、怎么改VsCode快捷键及代码片段

小齿轮—>键盘快捷方式---->搜索对应的键

ctrl+w 改为向下复制行

小齿轮---->用户代码片段

html.json js.json a.vue

5.7、解析json数据

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>5_ajax_解析json数据</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:ajax_解析json数据</h3><button id="btn">点我发送请求(原生js-ajax-get)</button><div id="content"></div><script type="text/javascript" >const btn = document.getElementById('btn')const content = document.getElementById('content')btn.onclick = ()=>{//实例xhrconst xhr = new XMLHttpRequest()//绑定监听xhr.onreadystatechange = ()=>{if(xhr.readyState === 4){if(xhr.status >= 200 && xhr.status <300){const {name,age,sex} = xhr.responsecontent.innerHTML = (`<ul><li>姓名:${name}</li><li>年龄:${age}</li><li>性别:${sex}</li><ul>`)}}}//配置请求xhr.open('GET','http://127.0.0.1:8080/get_person')//responseType用于指定返回数据的格式xhr.responseType = 'json'//发送请求xhr.send()}</script></body>
</html>

5.8、对象的连续结构赋值

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script type="text/javascript">let  obj={a:1,b:{c:2}}//  const {c}=obj.b; //标准的解构赋值写法console.log(c);const {b:{c}}=objconsole.log(c);//连续的机构赋值 react项目中会有这种写法//如何让c改个名字,重命名const {b:{c:value}}=objconsole.log(value);</script>
</body>
</html>

5.9、ajax请求的异常与超时处理

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>7_ajax请求的异常与超时处理</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:ajax请求的异常与超时处理</h3><button id="btn">点我发送请求(原生js-ajax-get)</button><div id="content"></div><script type="text/javascript" >const btn = document.getElementById('btn')const content = document.getElementById('content')btn.onclick = function(){//实例xhrconst xhr = new XMLHttpRequest()//绑定监听xhr.onreadystatechange = function(){if(xhr.readyState === 4){if(xhr.status >= 200 && xhr.status <300){const {name,age,sex} = xhr.responsecontent.innerHTML = (`<ul><li>姓名:${name}</li><li>年龄:${age}</li><li>性别:${sex}</li><ul>`)}}}//配置请求xhr.open('GET','http://127.0.0.1:8080/get_person_delay')//responseType用于指定返回数据的格式xhr.responseType = 'json'//配置出错的回调xhr.onerror = ()=>{alert('当前网络不稳定,请稍后重试');}//超时时间xhr.timeout = 2000 //超时的回调xhr.ontimeout = ()=>{alert('网速不给力,请切换网络重试');}//发送请求xhr.send()}</script></body>
</html>

6.0、取消请求

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>8_ajax取消请求</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:ajax取消请求</h3><button id="btn">点我发送请求(原生js-ajax-get)</button><button id="btn2">取消请求</button><div id="content"></div><script type="text/javascript" >const btn = document.getElementById('btn')const btn2 = document.getElementById('btn2')const content = document.getElementById('content')let xhr btn.onclick = ()=>{//实例xhrxhr = new XMLHttpRequest()//绑定监听xhr.onreadystatechange = function(){if(xhr.readyState === 4){if(xhr.status >= 200 && xhr.status <300){const {name,age,sex} = xhr.responsecontent.innerHTML = (`<ul><li>姓名:${name}</li><li>年龄:${age}</li><li>性别:${sex}</li><ul>`)}}}//配置请求xhr.open('GET','http://127.0.0.1:8080/get_person_delay')//responseType用于指定返回数据的格式xhr.responseType = 'json'//配置出错的回调xhr.onerror = ()=>{alert('当前网络不稳定,请稍后重试');}//超时时间xhr.timeout = 2000 //超时的回调xhr.ontimeout = ()=>{alert('网速不给力,请切换网络重试');}//发送请求xhr.send()}btn2.onclick = ()=>{xhr.abort()}</script></body>
</html>

5.1、避免重复发送请求

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>9_避免多次重复请求</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style></head><body><h3>该页面是测试:避免多次重复请求</h3><button id="btn">点我发送请求(原生js-ajax-get)</button><div id="content"></div><script type="text/javascript" >const btn = document.getElementById('btn')const content = document.getElementById('content')let xhr let isLoadingbtn.onclick = ()=>{if(isLoading) xhr.abort()//实例xhrxhr = new XMLHttpRequest()//绑定监听xhr.onreadystatechange = function(){if(xhr.readyState === 4){if(xhr.status >= 200 && xhr.status <300){isLoading = falseconst {name,age,sex} = xhr.responsecontent.innerHTML = (`<ul><li>姓名:${name}</li><li>年龄:${age}</li><li>性别:${sex}</li><ul>`)}}}//配置请求xhr.open('GET','http://127.0.0.1:8080/get_person_delay')//responseType用于指定返回数据的格式xhr.responseType = 'json'//发送请求xhr.send()isLoading = true}</script></body>
</html>

在绝对快的情况下,也不能保证发送的绝对是一次请求,但是防止大量的重复点击足够了、我们要优化就让这个按钮不能重复点击就好了

isLoading = false 提升下这个放置位置

5.2、测试Jquery封装的ajax

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>10_jQuery封装的ajax</title><style>#content{width: 300px;height: 100px;border: 1px solid black;margin-top: 10px;}</style><script type="text/javascript" src="./js/jquery.min.js"></script></head><body><h3>该页面是测试:jQuery封装的ajax</h3><button id="btn1">点我发送请求(jQuery-ajax-get)</button><button id="btn2">点我发送请求(jQuery-ajax-post)</button><div id="content"></div><script type="text/javascript" >const btn1 = $('#btn1')const btn2 = $('#btn2')const content = $('#content')btn1.click(()=>{//使用jQuery发送ajax-get(完整版)$.ajax({url:'http://127.0.0.1:8080/test_jquery_get', //请求地址method:'GET',//请求方式(默认值是GET)data:{school:'atguigu'},//携带的数据dataType:'json',//配置响应数据格式timeout:2000,//指定超时的时间success:(result,reponseText,xhr)=>{console.log(result,reponseText,xhr);content.append(`<div>汽车名:${result.name},价格:${result.price}</div>`)},//成功的回调error:(xhr)=>{console.log('请求出错了',xhr);} //失败的回调})//使用jQuery发送ajax-get(精简版)/* $.get('http://127.0.0.1:8080/test_jquery_get',{school:'atguigu'},(data)=>{console.log(data);content.append(`<div>汽车名:${data.name},价格:${data.price}</div>`)},'json') */})btn2.click(()=>{//使用jQuery发送ajax-post(完整版)$.ajax({url:'http://127.0.0.1:8080/test_jquery_post', //请求地址method:'POST',//请求方式(默认值是GET)data:{school:'atguigu'},//携带的数据dataType:'json',//配置响应数据格式timeout:2000,//指定超时的时间success:(result,reponseText,xhr)=>{console.log(result,reponseText,xhr);content.append(`<div>汽车名:${result.name},价格:${result.price}</div>`)},//成功的回调error:(xhr)=>{console.log('请求出错了',xhr);} //失败的回调})//使用jQuery发送ajax-post(精简版)$.post('http://127.0.0.1:8080/test_jquery_post',{school:'atguigu'},(data)=>{console.log(data);content.append(`<div>汽车名:${data.name},价格:${data.price}</div>`)},'json')})</script></body>
</html>

5.3、ajax的回调地狱问题

回调地狱是指一种不太好的编码形式,是一种套娃现象

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>11_演示回调地狱</title><script type="text/javascript" src="./js/jquery.min.js"></script></head><body><h3>该页面是测试:演示回调地狱(看代码)</h3><button id="btn1">点我发送请求(jQuery-ajax-get)</button><script type="text/javascript" >const btn1 = $('#btn1')btn1.click(()=>{//使用jQuery发送ajax-get(精简版)$.get('http://127.0.0.1:8080/test_jquery_get',{school:'atguigu'},(data)=>{console.log(data);$.get('http://127.0.0.1:8080/test_jquery_get',{school:'atguigu'},(data)=>{console.log(data);$.get('http://127.0.0.1:8080/test_jquery_get',{school:'atguigu'},(data)=>{console.log(data);},'json')},'json')},'json')})</script></body>
</html>

5.4、什么是同源策略

  1. 同源策略是由Netscape提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略。
  2. Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
  3. 所谓同源是指:协议,域名(IP),端口必须要完全相同 即:协议、域名(IP)、端口都相同,才能算是在同一个域里

5.5、为什么会有跨域这个问题?

原因是浏览器为了安全,而采用的同源策略(Same origin policy)

注意、同源策略是浏览器的一种限制

5.6、没有同源策略的危险场景

危险场景

有一天你刚睡醒,收到一封邮件,说是你的银行账号有风险,赶紧点进www.yinghang.com改密码。你着急的赶紧点进去,还是熟悉的银行登录界面,你果断输入你的账号密码,登录进去看看钱有没有少了,睡眼朦胧的你没看清楚,平时访问的银行网站是www.yinhang.com,而现在访问的是www.yinghang.com,随后你来了一条短信,钱没了,这个钓鱼网站做了什么呢?大概是如下思路:

<iframe id="baidu" src="https://www.baidu.com"></iframe><script type="text/javascript">const iframe = window.frames['baidu']const inputNode = iframe.document.getElementById('输入敏感信息的input的id')//现在是拿不到了,你能看到,但是你现在拿不到这里边的任何节点了console.log(inputNode.value)
</script>

非同源受到哪些限制

  1. Cookie不能读取;2、DOM无法获得;3、Ajax请求不能获取数据(能发是不能收)

5.7、JSONP解决跨域怎么解决跨域

要明确的是:JSONP不是一种技术,而是程序员“智慧的结晶”(利用了标签请求资源不受同源策略限制的特点)JSONP需要前后端人员互相配合。

前端页面写法

<body><button id="btn">按钮</button><script type="text/javascript">var btn = document.getElementById('btn');btn.onclick = function () {//1. 创建一个script标签var script = document.createElement('script');//2. 设置回调函数window.getData = function (data) {console.log(data);//拿到数据}//3. 设置script标签src属性,填写跨域请求的地址script.src = 'http://localhost:3000/jsonp?callback=getData';//4. 将script标签添加到body中生效document.body.appendChild(script);//5.不影响整体DOM结构,删除script标签document.body.removeChild(script);}</script>
</body>

后端写法

app.get('/jsonp', (req, res) => {//解构赋值获取请求参数const {callback} = req.query//去数据库查找对应数据const data = [{name: 'tom', age: 18}, {name: 'jerry', age: 20}];res.send(callback + '(' + JSON.stringify(data) + ')');
})

前端定义函数,后端返回数据的时候调用对用的函数,一切的一切都是因为你定义了对应的函数,这样后端传回来的值才能进行调用

jsonp解决跨域的原理就是绕开了xhr,借助script标签不受同源策略的影响,发送get请求,把数据给拿回来了,有一种前端定义函数,后端调用函数的感觉

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>Document</title></head><body><h3>当前页面一定不要用服务器去打开,因为要制造跨域问题,用jsonp去解决</h3><button id="btn">点我获取数据</button><script type="text/javascript" >const btn = document.getElementById('btn')btn.onclick = ()=>{//1.创建script节点const scriptNode = document.createElement('script')//2.给节点指定src属性(请求地址)scriptNode.src = 'http://localhost:8080/test_jsonp?callback=peiqi'//3.将节点放入页面document.body.appendChild(scriptNode)//4.准备好一个函数window.peiqi = (a)=>{console.log(a);}//5.移除已经使用过的script节点document.body.removeChild(scriptNode)}//前端给后端发个信息,你小子发信息的时候记住了,那个函数的名字叫做,demo,后端说不行,你这么写的话你得请我吃烧烤,没有原因,想吃烧烤了</script></body>
</html>

5.8、后台接口框架处理跨域问题

我是后端程序员,做java的处理跨域问题就非常的简单

1、我们有对应的@cors注解、或者配置SpringMVC的对应cors配置项、或者使用nginx解决跨域问题

2、使用vue的脚手架或者React脚手架的代理服务器(这个其实是webpack或者vite里边的一个模块提供的)

3、Node后端框架的处理:

res.set('Access-Control-Allow-Origin', 'http://localhost:63342');
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>测试cors解决跨域</title></head><body><h3>当前页面一定不要用服务器去打开,因为要制造跨域问题,测试cors解决跨域</h3><button id="btn">点我获取数据</button><script type="text/javascript" >const btn = document.getElementById('btn')btn.onclick = ()=>{const xhr = new XMLHttpRequest()xhr.onreadystatechange = ()=>{if(xhr.readyState === 4){if(xhr.status === 200){console.log(xhr.response);console.log(xhr.getAllResponseHeaders());}}}xhr.open('PUT','http://localhost:8080/test_put')xhr.send()}</script></body>
</html>

5.9、jquery封装的jsonp

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>Document</title><script type="text/javascript" src="./js/jquery.min.js"></script></head><body><h3>当前页面一定不要用服务器去打开,因为要制造跨域问题,jquery封装的jsonp</h3><button id="btn">点我获取数据</button><script type="text/javascript" >const btn = $('#btn')btn.click(()=>{$.getJSON('http://localhost:8080/test_jsonp?callback=?',{},(data)=>{console.log(data);})})</script></body>
</html>

页面无刷新获取数据,让用户的体验更好,不用频繁的跳转页面

Access-Control-Allow-Origin

访问-控制-允许-源

Access-Control-Expose-Headers

访问-控制-暴漏-请求头

Access-Control-Allow-Methods

访问-控制-允许-方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1552738.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

DC00025【含论文】基于协同过滤推荐算法springboot视频推荐管理系统

1、项目功能演示 DC00025【含文档】基于springboot短视频推荐管理系统协同过滤算法视频推荐系统javaweb开发程序设计vue 2、项目功能描述 短视频推荐系统分为用户和系统管理员两个角色 2.1 用户角色 1、用户登录、用户注册 2、视频中心&#xff1a;信息查看、视频收藏、点赞、…

分支和循环(1)

目录 前言 1.什么是语句&#xff1f; 2.分支语句&#xff08;选择语句&#xff09; 2.1 if 语句 2.2if书写格式形式的对比 2.3 if 练习 2.4 switch 语句 2.5 switch 练习 总结 前言 分支合循环首先就是要有良好的代码风格&#xff0c;缩进得当&#xff0c;要不然真的很…

横排文字、图层蒙版-1(2024年09月30日)

2024年09月30日 记录_导读 2024年09月30日 10:13 关键词 优惠券 设计 图层 背景 元素 调整 画笔工具 颜色 大小 位置 复制 移动 添加涂层 多选 显示 PS 元素文件 隐藏 使用规则 Logo 全文摘要 通过在Photoshop中精心操作图层&#xff0c;包括复制、移动和调整设置&#xf…

结构型模式-适配器-桥接-外观-代理

适配器模式 是什么 将一个类的接口转换成客户希望的另外一个接口 解决接口不兼容问题,复用之前的代码 实例 public class PoliceCarAdapter extends CarController { private PoliceSound sound;//定义适配者PoliceSound对象 private PoliceLamp lamp;//定义适配者Polic…

虚拟机U盘启动

二、注意事项 1、正确顺序是先插入U盘启动盘&#xff0c;再打开虚拟机&#xff0c;否则虚拟机无法检测到U盘&#xff1b; 2、如果已经打开虚拟机&#xff0c;则需关闭&#xff0c;插入U盘后重新开启。 3、设置好后如果换另一个U盘进行U盘启动&#xff0c;以下步骤要重新再设置&…

Python核心知识:pip使用方法大全

什么是 pip&#xff1f; pip 是 Python 的包管理工具&#xff0c;允许用户安装、升级和管理 Python 的第三方库和依赖。它极大地简化了开发过程&#xff0c;使开发者可以轻松地获取并安装所需的软件包。pip 已成为 Python 项目中最常见的包管理工具&#xff0c;并且自 Python …

windows C++-UWP 应用中使用 HttpRequest 类

在 UWP 应用中使用 HttpRequest 类 本节演示在 UWP 应用中如何使用 HttpRequest 类。 应用程序会提供一个输入框&#xff0c;该输入框定义了一个 URL 资源、用于执行 GET 和 POST 操作的按钮命令和用于取消当前操作的按钮命令。 使用 HttpRequest 类 1. 在 MainPage.xaml 中…

8639 折半插入排序

### 思路 折半插入排序是一种改进的插入排序算法&#xff0c;通过二分查找来确定插入位置&#xff0c;从而减少比较次数。每次插入时&#xff0c;先用二分查找找到插入位置&#xff0c;然后将元素插入到正确的位置。 ### 伪代码 1. 读取输入的待排序关键字个数n。 2. 读取n个待…

class 030 异或运算的骚操作

这篇文章是看了“左程云”老师在b站上的讲解之后写的, 自己感觉已经能理解了, 所以就将整个过程写下来了。 这个是“左程云”老师个人空间的b站的链接, 数据结构与算法讲的很好很好, 希望大家可以多多支持左程云老师, 真心推荐. https://space.bilibili.com/8888480?spm_id_f…

【CKA】五、网络策略–NetworkPolicy

5、配置网络策略–NetworkPolicy 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 1、根据题目分析要创建怎样的网络策略 2、按题目要求查看ns corp-net的label 3、编写yaml&#xff0c;其中注意 namespace、label、port 3. 官网地址&#xff1a; https://kubernetes.io/…

解决connect因父类不明确而报错的问题

如图所示&#xff0c;connect函数报错&#xff0c;原因是connect的检查是在编译期完成的&#xff0c;而传入父类则是在运行时&#xff0c;从而引起connect不知道parent是谁而报错。只需加入类型转换即可。 connect(qobject_cast<TableWidget*>(parent), &TableWidg…

STM32F1+HAL库+FreeTOTS学习15——互斥信号量

STM32F1HAL库FreeTOTS学习15——互斥信号量 1. 优先级翻转2. 互斥信号量3. 相关API函数&#xff1b;3.1 互斥信号量创建3.2 获取信号量3.3 释放信号量3.4 删除信号量 4. 操作实验1. 实验内容2. 代码实现3. 运行结果 上期我们介绍了数值信号量。这一期我们来介绍互斥信号量 1. 优…

【计算机毕业设计】springboot企业客户信息反馈平台

摘 要 网络的广泛应用给生活带来了十分的便利。所以把企业客户信息反馈管理与现在网络相结合&#xff0c;利用java技术建设企业客户信息反馈平台&#xff0c;实现企业客户信息反馈的信息化。则对于进一步提高企业客户信息反馈管理发展&#xff0c;丰富企业客户信息反馈管理经验…

官网:视觉是第一记忆,没有记忆点的官网设计是失败的。

官方网站虽然不像之前那么火爆了&#xff0c;但是依然是企业展示品牌形象和吸引用户的重要渠道。仅仅拥有一个官方网站并不足以吸引用户&#xff0c;更重要的是网站的设计是否能够给用户留下深刻的记忆。 当前&#xff0c;用户对于网站的要求也越来越高&#xff0c;他们不仅仅希…

Arduino UNO R3自学笔记16 之 Arduino的定时器介绍及应用

注意&#xff1a;学习和写作过程中&#xff0c;部分资料搜集于互联网&#xff0c;如有侵权请联系删除。 前言&#xff1a;学习定时器的功能。 1.定时器介绍 定时器也是一种中断&#xff0c;属于软件中断。 它就像一个时钟&#xff0c;可以测量事件的时间间隔。 比如早…

重置linux后vscode无法再次使用ssh连接

如果你使用过vscode ssh远程连接了一个Linux系统&#xff0c;但该系统被重置了&#xff0c;并且关键配置没有改变。再次使用vscode连接时&#xff0c;vscode可能无法连接。 原因&#xff1a;vscode远程连接后会在C:\Users{{你的用户名}}.ssh下的known_hosts和known_hosts.old。…

停止模式下USART为什么可以唤醒MCU?

在MCU的停止模式下&#xff0c;USART之类的外设时钟是关闭的&#xff0c;但是USART章节有描述到在停止模式下可以用USART来对MCU进行唤醒&#xff1a; 大家是否会好奇在外设的时钟被关闭的情况下&#xff0c;USART怎么能通过接收中断或者唤醒事件对MCU进行唤醒的呢&#xff1…

2024多模态大模型发展调研

随着生成式大语言模型应用的日益广泛&#xff0c;其输入输出模态受限的问题日益凸显&#xff0c;成为制约技术进一步发展的瓶颈。为突破这一局限&#xff0c;本文聚焦于研究多模态信息的协同交互策略&#xff0c;旨在探索一种能够统一理解与生成的多模态模型构建方法。在此基础…

基于springboot+小程序的在线选课管理系统1(源码+sql脚本+视频导入教程+文档)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于springboot小程序的在线选课管理系统实现了管理员、教师及学生。 1、管理员实现了首页、个人中心、管理员管理、教师管理、学生管理、课程信息管理、选课信息、公告管理、论坛管理、基…

Redis哨兵模式的搭建以及配置参数简介

原理 Redis哨兵模式是一种用于在Redis主从复制环境中进行高可用性监控和故障恢复的机制。该模式引入了一个或多个哨兵节点&#xff0c;这些节点负责监控Redis服务器的状态&#xff0c;并在主节点发生故障时切换为新的主节点。 哨兵节点的工作原理如下&#xff1a; 1、哨兵节点…