一、前提上网:
- 首先,我们大家肯定会上网,打开浏览器,在地址栏,输入网址,就会加载到哪个网页,就会出现想看见的信息。
- 比如:我们在地址栏上输入百度的网址(百度一下,你就知道),或者直接输入文字百度,点击回车,百度的页面就呈现在我们的眼前
- 这是我们肉眼看到的,那么这些是怎么做到的呢?
- 我简单介绍一下所有的人物:
客户端:我们自己现在用的电脑
服务器:别人的电脑
用户:自己
浏览器:这不用介绍了,我想大家要具备独立思考和查阅资料的能力...
二、输入地址到显示页面,如何实现?
- 接下来步入正题:如何实现的,这些人物之间发生了什么事
- 首先:用户输入地址之后,点击回车,浏览器开始工作,他去查找这个地址,然后向服务器发起一个http请求,服务器接收到请求,然后他去处理这次请求,返回一个响应,(去处理这次请求,就理解成看看客户端和我要的什么数据,比如要的是百度的数据,你不能给我京东的吧,返回响应就简单理解为返回你要的数据),浏览器这边开始构建DOM树,然后并行下载服务器返回的资源,浏览器通过计算节点,显示到页面,我们就看见页面了。
其实就跟正常生活叙述一样:(只是为了理解这个操作,不要从特别难的角度去看待这个问题,他们也只是机器,机器做了什么事而已,认真反复思考一下,别害怕)
我举个例子:小记要吃油麦菜,大婶去买菜,疫情不方便,要通过第三方,这个大婶就相当于浏览器,菜市场就是服务器,菜就是数据,第三方就是Ajax。
小记说要吃油麦菜,大婶去买菜,看看菜市场哪里属于卖油麦菜的呀,她通过第三方工作人员,告诉他要买菜这个事。菜市场知道了,他找到油麦菜,给第三方工作人员,大婶就准备要做这道菜的材料,然后把菜洗洗,哆哆,这道菜就做好了。
三、Ajax的几个疑问?
1.什么是Ajax?它实现了什么?
Ajax指⼀种创建交互式⽹⻚应⽤的⽹⻚开发技术,实现了页面不刷新就能更新数据。
2.Ajax什么时候使用?
不更新向后台请求数据的时候,比如搜索栏,下方相关提示,你输入王者荣耀,搜索栏下方出现和他有关的语句,这个时候就可以使用Ajax。
如何实现:获取到搜索栏输入的内容,发起请求,服务器就会响应给我们相关的数据,我们把数据显示在页面上,就实现这个效果了。
3.为什么使用Ajax?
传统情况下,浏览器向服务器发起请求,要等待响应才能继续再发起请求,这样就太慢了,这就是同步,只能等一件事做完再去做另一件事,这个时候Ajax就出现了,她能发起异步,再做一件事时,还能同时去做很多事,是异步操作。
四、Ajax的使用步骤
js原生的get请求:
xhr.open() 发起请求
xhr.send() 发送请求
xhr.οnlοad=function(){}响应事件xhr.responseText 从服务器响应回来的数据
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') 设置响应头
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://www.baidu.com/?name=大婶')
xhr.send()
xhr.onload = function () {
console.log(xhr.responseText);
}
js原生的post请求:
var xhr = new XMLHttpRequest()
xhr.open('post', 'http://www.baidu.com')
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send('name=90&age=90')
xhr.onload =function () {
console.log(xhr.responseText);
}
五、封装Ajax
function ajax(options) {
var defaults = {
type: 'get',//请求方式
url: '',//地址
params: {},//参数
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},//请求头
success: function() {},//成功的回调函数
error: function() {}//失败的回调函数
}
Object.assign(defaults, options)//Object.assign覆盖:用options的值覆盖defaults的值
var type = defaults.type.toUpperCase()//把请求方式全转为大写,目的为了写geT也没关系
if (type == 'GET' || type == 'POST') {
var params = defaults.params
var paramArr = []
var paramString = ''
for (const key in params) {//遍历对象用forin
paramArr = key + '=' + params[key]//对象[属性名]:这样取出来的值是属性值
}
paramString = paramArr.join('&')//把{name:'hh',age:'xx'}转为'name=hh&age=xx'
var url = defaults.url
if (type == 'GET') {
url = defaults.url + '?' + paramString//get请求字符串要拼在地址栏后
}
var xhr = new XMLHttpRequest()
xhr.open(type, url)
var data = null
if (type == 'POST') {
data = paramString
var contentType = defaults.header['Content-Type']
if (contentType == 'application/json') {
data = JSON.stringify(params)
}
xhr.setRequestHeader('Content-Type', contentType)
}
xhr.send(data)
xhr.onload = function() {
if (typeof defaults.success == 'function') {
var responseText = xhr.responseText
if (xhr.getResponseHeader('Content-Type').includes('application/json')) {
responseText = JSON.parse(xhr.responseText)
}
if (xhr.status == 200) {
defaults.success(responseText, xhr)
} else {
defaults.error(responseText, xhr)
}
}
}
xhr.onerror = function() {
alert('网络中断,无法发送Ajax请求')//没有网络时,会触发onerror事件
}
} else {
console.log('参数错误');
return;//阻止向下执行
}
}
六、跨域
1.什么是同源策略?
协议、域名、端口号都相同才算同源,有一个不同都不是同源
http://cc.www.baidu.com/edit/create?name=123&age=12
协议:http
域名:www.baidu.com
端口:80(http默认端口号是80)
参数:?后面的
举例:
http://www.hhh.cn:34/ccc/jjj?hh=00&yy=0
协议:http
域名:www.hhh.cn
端口号:34
2.为什么产生跨域?
跨域就是不能访问别人的网站,浏览器有个规定,就是同源策略,为了防止黑客攻击网站,这是咋回事呢?
假如你登录一个网站后,你没退出,你的登录信息保存在cookie中,黑客做一个和你刚才一样的网站,获取到你的信息,那你要是登录的支付宝,不都给你整没了。
3.怎么跨域?
别学坏奥,有时候开发还是要用到跨域的,要请求别人的服务器
比如你自己就有两个,A想请求B,这不就需要解决一下这个问题了吗
我接下来先介绍三种解决跨域的办法
1.jsonp
2.cors
3.服务器
3.1 jsonp实现跨域
实现原理:因为script标签的src属性不受同源策略限制
我们看见这个问题的答案总是要动态创建script标签,那么为啥要动态创建,我直接在html里写一个不就行了吗
<script src="http://www.baidu.com"></script>
jsonp只支持get请求
因为要控制她,所以要动态创建,直接写在页面上,他页面刷新直接请求了,我们想让他比如点击按钮之后再发起请求,所以动态创建,这样就可以再点击事件的时候再发起请求,后面为啥移除她,因为不移除,每发起一次请求都会生成 一个script标签。
案例:
<button id="btn">发送请求</button>
<script>
function fn1(data) {
console.log(data);
}
</script>
<script>
var btn = document.getElementById('btn')
btn.onclick = function() {
var script = document.createElement('script')
script.src = 'https://wis.qq.com/weather/common?callback=fn1'
document.body.appendChild(script)
script.onload = function() {//script.onload事件 等script响应回数据后移出她
document.body.removeChild(script)
}
}
</script>
把json数据通过字符串从服务器传递给浏览器,浏览器接受执行js代码
通过动态创建script标签,src的属性不受同源限制的原理解决跨域问题
script标签 接收服务器响应得字符串数据,有一个函数在最上面被调用
能够拿到响应数据 处理数据
是一个模拟Ajax得请求方式
封装jsonp:
function jsonp(options) {
var script = document.createElement('script')
var fnName = 'Jsonp' + Math.random().toString().replace('.', '')
window[fnName] = options.success
var paramString = ''
for (const key in options.params) {
paramString += '&' + key + '=' + options.params[key]
}
script.src = options.url + '?callback=' + fnName + paramString
document.body.appendChild(script)
script.onload = function() {
document.body.removeChild(script)
}
}
3.2 CORS实现跨域
// 客户端:正常发起ajax请求
// 服务端:设置下面两行
允许谁访问,把*换成网站url就行
res.header('Access-Control-Allow-Origin', '*')//*表示允许所有网站访问
res.header('Access-Control-Allow-Methods', 'get,post,put,delete')//表示允许用什么方式访问
3.3 服务器实现跨域
服务器不受同源策略限制,所以可以自己的网站访问自己服务器,再用自己服务器访问别人网站
客户端: xhr.withCredentials=true //客户端在发起ajax的时候,加上这一行
xhr.withCredentials=true //意思是允许客户端在发起HTTP请求时携带cookie
服务端:
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'get')
res.header('Access-Control-Allow-Credentials', true)