http及Ajax
1.前后端通信
1.1前后端通信是什么?
- 前端和后端数据交互的过程
- 浏览器和服务器之间数据交互的过程
- 后端向前端发送数据的过程:访问页面
- 前端向后端发送数据的过程:用户注册
前后端通信的过程?
- 浏览器向服务器请求数据
- 服务器给浏览器响应数据
- 前后端通信的过程是在**“请求-响应”**中完成的
前后端的概念解释?
- 前端:浏览器端
- 客户端:只要能够与服务器通信的都交客户端
- 用命令行工具:curl +网址,可获取请求网址的数据
- 后端:服务器端
前后端的通信方式?
- 浏览器访问网页:在浏览器地址栏输入网址,按下回车
- HTML的标签:浏览器在解析HTML标签的时候,遇到一些特殊的标签,会再次向服务器发送请求:
- 比如:link/img/script/iframe文件
- 还有一些标签,浏览器解析的时候,不会向服务器发送请求,但是用户可以使用他们向服务器发送请求:比如:a/from
- **Ajax和Fetch:**先不过多讲解
Http是什么?
- HyperText Transfer Protocol:超文本传输协议(HTTP)
- HyperText Markup language:超文本标记语言(HTML)
什么是超文本?
- 原先一个个单一的文本,通过超链接将其联系起来,由原先的单一的文本变成了可无限延伸、扩展的超级文本、立体文本
- HTML、JS、CSS、图片、字体、音频、视频等等文件,都是通过HTTP在服务器间传输的。
- 每一次前后端通信,前端都必须主动向后端发送请求,后端接收到前端请求后,可以给出响应
- HTTP是一个请求-响应协议
http请求响应的过程?
- 第一步:浏览器会先查询输入网址的IP地址,先到浏览器缓存中查看是否访问过这个IP地址
- 第二步:如果访问过,就获取相对应的IP地址,并与服务器建立TCP连接,进行HTTP请求
- 第三步:如果浏览器缓存中没有这个IP地址,就需要到DNS域名解析服务器中查询,查询到后并放入到缓存中,以便下次访问直接获取,并进行第二步
- 还可以在repl环境下,NetWork窗口下查看Size属性
- Size表示下载的大小
- memory cache:内存缓存,存取最快
- disk cache:硬盘缓存,存取较慢
- 48kb:需要下载,存取最慢
http报文是什么?
- 浏览器向服务器发送请求时,请求本身就是信息,叫做请求报文
- 服务器向浏览器发送响应时传输的信息,叫做响应报文
http报文的格式?
- 请求:
- 请求头:起始行+首部
- 请求体
- 响应:
- 响应头:起始行+首部
- 响应体
- GET请求没有请求体,通过请求头传递数据,所以Ajax的xhr.send(),里面传null
- Post请求有请求体,通过请求体传递数据,所以Ajax的xhr.send(),里面传数据
常用http的方法?HTTP方法的语义?RESTful接口设计?
-
常用方法:浏览器发送请求时采用的方法,和响应是无关的,这些方法是用来定义对于资源采用什么样的操作,有各自的语义
-
GET:获取数据(查)
-
POST:创建数据(增);注册
-
PUT:更新数据(改);修改个人信息
-
DELETE:删除数据(删);删除内容
-
这些方法虽然有各自语义,但是并不是强制性的,PUT和DELETE不常用,经常用POST来代替
-
-
RESTful接口设计风格:
- 一种接口设计风格,充分利用HTTP方法的语义
- 当我们用普通方式增删改查数据时,就需要四个对应的接口
- 当我们用RESTful时,只写一个接口,让后端根据请求方法(GET、POST、PUT、DELETE)来判断想通过这个接口进行什么操作
GET和POST方法的对比?
-
语义:
- GET:获取数据
- POST:创建数据
-
发送数据:
-
GET:通过地址,在请求头中携带数据,能携带的数据量和地址的长度相关联,一般最多为几k
-
POST:即可以通过地址在请求头中携带,也可以通过请求体携带数据。但是一般不会在请求头中
-
如果携带少量的数据,可以使用GET请求,大量的数据可以使用POST
-
结论:当我们查询数据时,只需要向后台发送少量的几个查询条件即可,这时用GET请求绰绰有余,而当我们在创建数据时,可能发送给后台几百k到几兆的数据,这时POST请求才更合适。
-
-
缓存:
- GET可以被缓存,POST不会被缓存
- 浏览器缓存的是访问时请求的地址信息,POST是通过请求体隐式请求的,所以不会被缓存
-
安全性:
- GET的请求数据在携带在网址中,并且有缓存
- POST的请求数据可以在请求体中看到
- 所以,两个请求不加密都不安全
- 发送密码等其他敏感信息时,不要用GET:可以窥屏或在缓存中找到
HTTP状态码是什么?HTTP状态码语义?
-
定义服务器对请求的处理结果,是服务器返回的
-
语义:
-
1xx:消息,代表请求已经被接收,需要进一步处理
-
2xx:成功
-
3xx:重定向,老网址重定向到新网址
- 301 Moved Permanently:永久性的跳转
- 302 Move Temporarily:临时性的跳转
- 304 Not Modified:没有过期,直接用缓存就行
-
4xx:客户端错误,请求错误
-
5xx:服务器错误
2.本地存储
Cookie和localStroge
Cookie
什么是Cookie?
- Cookie的全称是HTTP Cookie,简称Cookie
- 是浏览器存储数据的一种方式:存储在用户本地,而不是存储在服务器上,是本地存储
- 一般会自动随着浏览器每次请求发送到服务器端
Cookie有什么用?
- 利用Cookie跟踪统计用户访问该网站的习惯,比如什么时间访问,访问了哪些页面,在每个页面的停留时间。
- 不要在Cookie中保存密码等信息,太容易被发现了。
如何使用Cookie?
-
如何查看:
- 在repl环境中的Application中可以检查Cookie
- 如果Cookie中有内容,在请求头中就会存在一个Cookie的键值对
-
如何获取:
-
document.cookie:获取cookie中存放的所有内容
-
username=sjh; language=cn;
-
键与值之间用=号连接,键值对与键值对之间用;+空格隔开
-
如何写入Cookie,如何读取Cookie?
-
写入:不能一起设置,只能一个一个设置
-
读取:读取的是一个由名值对构成的字符串,每个名值对之间由"; "(一个分号一个空格)隔开的,不能一个一个获取cookie,只能一下全部获取。
-
// 写入:不能一起设置,只能一个一个设置 document.cookie="username=sjh"; document.cookie="age=18"; // 读取cookie:读取的是一个由名值对构成的字符串,每个名值对之间由"; "(一个分号一个空格)隔开的 document.cookie;//'age=18; username=sjh'
…
-
Cookie的属性?
Coolie的关键属性:名称和值
、失效时间
(Expries或者Max-Age)、Domain、PATH、HttpOnly、Secure
-
名称(Name)和值(Value):“username=sjh”
-
最重要的两个属性,创建Cookie时必须填写,其它属性可以使用默认值
-
Cookie的名称或值如果包含非英文字母,则写入时需要使用**encodeURIComponent()编码,读取时使用decodeURIComponent()**解码。
-
//名或值存在非英文情况 //用模板字符串拼接 document.cookie=`${encodeURIComponent("用户` 名")}=${encodeURIComponent("张三")}`;
-
一般名称使用英文字母,不要用中文,值可以用中文,但是要编码
-
encodeURIComponent:函数编码的字符串(编码)
-
decodeURIComponent:函数解码的字符串(解码)
-
-
失效(到期时间)
-
对于失效的Cookie,会被浏览器清除
-
**会话Cookie(内存Cookie):**存放在内存中,当会话结束时,也就是浏览器关闭时,Cookie就消失了
- 如果没有设置失效(到期时间),这样的Cookie称为会话Cookie,会话Cookie在的Expres/Max-Age中查看
-
硬盘Cookie:想让Cookie长时间存在,需要设置Expries或者Max-Age
-
expries:参数是时间对象,表示到这个时间再删除
-
max-age:参数是数值,表示Cookie存活多少秒
// expires //值为Date document.cookie=`username=sjh; expires=${new Date('2010-1-01 00:00:00')}` // max-age // 值为数字,表示当前时间+多少秒后过期,单位是秒 //如果max-age的值是0或者负数,则Cookie会被删除 document.cookie=`username=aaa; max-age=10`;//Cookie存活10秒
-
-
-
Domain域:限制了访问Cookie的范围(不同域名下 )
-
如果想让两个不同前缀的网址都能够访问一个cookie属性,只需要将两个网址相同的父域提取出来作为Domain值即可
-
使用JS只能够读写当前域或者父域的Cookie,无法读写其他域的Cookie
-
// www.baidu.com m.baidu.com 当前域 // .baidu.com 父域 document.cookie=`username=sss; domian=www.baodu.com`;
-
-
-
Path:限制了访问Cookie的范围(同一域名下)
-
内层目录可以访问到外层目录的Cookie,但是外层无法访问到内存
-
使用JS只能读写当前路径或上级路径的Cookie,无法读写下级域的Cookie
-
document.cookie=`username=sss; path=course/list`
-
-
-
当Name、Domain、Path完全相同时,才被视为是一个Cookie可以用作用域的概念来理解。
-
HttpOnly:设置了HttpOnly属性,这个Cookie就不能通过JS访问了,目的是为了安全性
-
Secure:安全标志,只在https下能够发送这个cookie,在http下不让发送这个cookie
-
JS写法:
-
document.cookie=`username=sss; secure`//不用填值
-
-
-
Domain、Path、Secure都要满足条件,还不能过期的Cookie,才会被发送到服务器端
封装Cookie,实现增删改查Cookie?
- 增:需要能够同时设置:名值对(必要)、Max-age、Domain、Path、Secure
- 查:通过name属性获取Cookie值
- 删:借助set方法,将对应cookie的存活时间设为负数
// 增:需要能够同时设置:名值对(**必要**)、Max-age、Domain、Path、Secure
let set=(name,value,{maxage,domain,path,secure}={})=>{
let str="";
str+=`${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
if(typeof maxage=='number'){
str+=`; max-age=${maxage}`;
}
if(domain){
str+=`; domain=${domain}`;
}
if(path){
str+=`; path=${path}`;
}
if(secure){
str+=`; secure`;
}
document.cookie=str;
}
// 查:通过name属性获取Cookie值
let get=(tname)=>{
// 获取当前页面的所有cookie
let uname=encodeURIComponent(tname);
let arr= document.cookie.split("; ");
for(let item of arr){
let [CookieName,CookieVal]=item.split("=");
if(CookieName==uname){
return decodeURIComponent(CookieVal) ;
}
}
return;
}
// 删:借助set方法,将对应cookie的存活时间设为负数
let remove=(name)=>{
set(name,"",{maxage:-1});
}
export {set,get,remove};
使用封装好的cookie实现网站语言的切换?
import {set} from "./cookie.js";
let cn=document.getElementById("cn");
let en=document.getElementById("en");
// 通过添加cookie设置中英文
cn.onclick=function(){
set("language","cn",{maxage:30*24*3600});
let href= window.location.href;
// console.log(href);
window.location.href="";
}
en.onclick=function(){
set("language","en",{maxage:30*24*3600});
let href= window.location.href;
// console.log(href);
window.location.href="";
}
Cookie注意事项?
- 前后端都可以写入和获取Cokie
- Cookie有数量限制
- 每个域名下的Cookie数量有限,当超过单个域名限制之后,浏览器就会清除以前设置的Cookie
- Cookie有大小限制
- 每个Cookie的存储容量很小,最多只有4kb左右
LocalStorage
localStorge是什么?
-
localStorge也是浏览器存储数据的方式(本地存储),它只是存储在本地,不会发送到服务器端
-
单个域名下的localStorage总大小有限制,不同浏览器的限制不同。
-
**localStorage:**在Application下查看
-
**sessionStorage:**会话存储,当会话结束时,sessionStorage会被清除,其他用法与localeStorage完全相同
-
用法:
-
// 设置一个键值对 localStorage.setItem("username","史佳豪"); // 获取 localStorage.getItem("username");//"史佳豪" localStorage.getItem("age");//null,获取不存在的返回null // length localStorage.length;//是一个有长度的对象 // removeItem localStorage.removeItem("username"); localStorage.removeItem("age");//删除不存在的键也不会报错 // clear localStorage.clear();//删除所有的键值对
-
使用localStorage实现自动填充?
-
// 实现自动填充 let form=document.getElementById("form"); let btn=document.getElementById("btn"); form.username.value=localStorage.getItem("username"); btn.onclick=function(){ let content= form.username.value; if(content){ localStorage.setItem("username",content); } }
localeStorage的注意事项?
- localStorage的存储期限:localStorage是持久化的存储,除非手动清除(比如通过js删除,或者清缓存),否则数据永远不会过期。
- **sessionStorage:**会话存储,当会话结束时,sessionStorage会被清除,其他用法与localeStorage完全相同
- localeStorage键和值类型:localeStorage存储的键和值只能是字符串类型,不是字符串类型的,也会先转为字符串类型再存进去,所以取出来的键和值都是字符串类型
- 不同域名下不能共用LocaleStorage。
- localeStorage的兼容性:IE7及以版本不支持localStorage,IE8开始支持。
- http://www.caniuse.com:查看方法的版本兼容性
3.AJAX
1.什么是AJAX?
- Ajax是Asynchronous JavaScript and XML(异步JavaScript和XML)的缩写
- Ajax就是浏览器与服务器之间的一种异步通信方式,以前使用XML格式传输数据,现在用JSON
- 使用Ajax可以在不重复加载整个页面的情况下,对页面的整体进行
- Ajax必须在服务器环境下使用,文件环境很多浏览器不支持Ajax
2.Ajax的异步是什么,XML是什么?
-
异步:可以异步地向服务器发送请求,在等待响应的过程中,不会阻塞当前页面的继续加载,浏览器可以做自己的事情,直到响应成功后,浏览器才开始处理响应数据。
-
XML:(可扩展标记语言),是前后端数据通信时传输数据的格式,是一种过气的数据传输格式
3.AJAX的基本用法之XMLHttpRequest?
- Ajax想要实现浏览器与服务器之间的异步通信,需要依靠XMLHttpRequest,它是一个构造函数
4.AJAX的使用步骤?
-
一、创建xhr实例对象:let xhr=new XMLHttpRequest();
-
四、监听事件,处理响应:
-
xhr.readystatechange=function(){ if(xhr.readyState!=4) return; if(xhr.status>=200&&xhr.status<=300||xhr.status==304){ //状态值必须为4 //状态码必须为200-299,或者304 //才能真正获取到数据 let data=xhr.responseText; } }
-
-
二、准备发送请求:xhr.open(method、url、是否异步);调用open不会真正的发送请求,而是做好请求准备工作
-
三、发送请求:
- GET方法:xhr.send(null)
- POST方法:xhr.send(携带的数据)
-
监听事件最好放在open之前监听,尽早的监听状态值变化
5.readyState的五个状态?
- 0:未初始化,尚未调用open()
- 1:启动,已经调用open(),但尚未调用send()
- 2:发送,已经调用send(),但尚未接收响应
- 3:接收,已经接受大部分响应数据
- 4:完成,已经接收到全部响应,而且已经可以在浏览器中使用了
6.GET请求如何携带数据的?数据编码如何处理?
- 携带数据:
- GET请求没有请求体,所以只能用请求头携带数据,在url中以==?username=“sjh”&age=11==的方式携带
- 如果在xhr.send()中携带了数据,不会报错,也不会发送出去
- 数据编码:
- 如果携带的数据是非英文字母,就需要先进行编码,再传给后台,可以使用encodeURIComponent()
3.1.JSON
7.POST请求如何携带数据?
- 携带数据:
- POST请求主要通过请求体携带数据,也可以通过请求头来携带
- 直接将参数写在xhr.send()方法里,一般是字符串,但是经常写为两种格式:
- 名值对:xhr.send(‘username=sjh&age=18’)
- JSON:xhr.send({username})
- send方法中不能直接传递对象,需要先将对象转为字符串的形式
- 数据编码:
- 如果携带的数据是非英文,就需要先进行编码,再传给后台,可以使用encodeURIComponent()
8.JSON是什么?
- JSON是AJAX发送和接收数据的一种格式
- JSON实质上就是将js对象转为字符串,并且保留对象中的内容
- JSON全程是JavaScript Object Notation:js对象表示法
9.为什么需要JSON?
- JSON有三种形式,每种形式的写法都和JS中的数据类型很像,可以轻松的和JS中的数据类型转换
- JS中数据格式,后端不认识,所以需要一种两方都兼容的格式:JS->JSON->PHP/Java
10、JSON的三种形式?
-
简单值形式:就是对应着JS的基本数据类型:数字、字符串、布尔值、null(不能有undefined)
- 注意事项:
- JSON中没有undefined
- JSON中不能有注释
- JSON中字符串必须用双引号
- 注意事项:
-
对象形式:一般表示一个数据,与JS中对象形式相似
- 注意事项:
- JSOn中对象属性名,以及字符串属性值,必须加双引号
- JSON中只要涉及到字符串,必须用双引号
- 属性名和属性值不支持undefined
- 注意事项:
-
数组形式:一般表示一组数据,与JS中数组形式相似
- 数据项不支持undefined
- 数组中字符串必须用双引号
- JSON中只要涉及到字符串,必须用双引号
11、JSON两个常用有哪些?
- JSON.parse(str):将JSON字符串转为JS对象数据类型,一定要是合法的JSON字符串
- JSON.stringify(obj):字符串化,将JS对象转为JSON字符串
12.使用JSON.parse()和JSON.stringify()封装localeStorage?
let storage=window.localStorage;
//不管是不是对象类型,先转为字符串JSON类型,再新增值
function set(key,value){
storage.setItem(key,JSON.stringify(value));
}
//获取storage对应数据后先转换为对象,再输出
function get(value){
return JSON.parse(storage.getItem(value)) ;
}
function remove(key){
storage.removeItem(key);
}
function clear(){
storage.clear();
}
export {set,get,remove,clear};
3.2.跨域
13.跨域是什么?
- 同域:与请求的网址在同一网域(协议+域名+端口号相同),就称为同域
- 跨域:与请求的网址在不同网域(协议+域名+端口号不同),就称为跨域
- 向一个域发送请求,如果请求的域和当前域是不同域,就叫做跨域
- 不同域,跨域请求,浏览器会认为它不安全,就拦截了
14.什么是同域,什么是不同域?
- https(协议)😕/www.mooc.com(域名):443(端口号)/course/list(路径)
- 协议、域名、端口号、任何一个不一样,就是不同域
- 与路径无关、路径一不一样无所谓
- http与https两个协议不相同
15.跨域请求为什么会被阻止掉?
-
阻止跨域请求是浏览器本身的一种安全策略–同源策略
-
其他客户端或服务器端都不存在跨域被阻止的问题
-
解决方案:
- CORS跨域资源共享(优先使用)
- JSONP script(兼容性高)
16.CORS跨域资源共享?
CORS:跨域资源共享
-
跨域请求不是前端能决定的,而是后端配置的
-
在响应头中,存在Access-Control-Allow-Origin:*
- 表示允许所有的域名来跨域请求它,*是通配符,没有任何限制
-
只允许指定域名的跨域请求:Access-Control-Allow-Origin:
http://127.0.0.1:5050
-
我们能做的就是告诉后端,我想获取你的请求,你得打开跨域
-
兼容性:IE10及以上版本的浏览器可以正常使用CORS
17.使用CROS跨域的过程?理解
-
浏览器发送请求
-
后端在响应头中添加Access-Control-Allow-Origin头信息
-
浏览器接收到响应
- 如果同域下的请求,浏览器放行
- 如果跨域请求,浏览器查看响应头有没有允许跨域访问的信息
- 如果允许跨域,浏览器方行
- 如果不允许跨域,拦截,丢弃响应
18.JSONP的实现原理?
- script标签跨域不会被浏览器阻止
- JSONP利用script标签,加载跨域文件
- 如何实现:
- 服务器准备好JSONP接口
- 手动或动态加载JSONP接口:将请求地址放到script标签src属性里进行访问
3.3.XHR实例 对象
1.XHR的属性?
- xhr.responseType=‘text’;设置响应数据的类型,默认就是text类型
- text:文本类型,用response或responseText获取的没区别
- json:json字符串类型,这时就不能用responseText获取了,只能用response
- xhr.response:获取响应数据。
- xhr.responseText:获取文本类型的响应数据
- xhr.timeout=10000;在open()之后,send之前设置,设置请求的超时时间(毫秒),一般与timeout事件一起使用
- withCredentials:指定使用Ajax发送请求时是否携带Cookie
- 使用Ajax发送请求,默认情况下,同域时,会携带Cookie,跨域时,不会
- xhr.withCredentials=true;不管同域跨域,都携带Cookie
- 最终能否成功的携带Cookie,还是要看服务器是否同意:Access-Control-Allow-Origin:不能用*,而是指定可跨域的域名
2.XHR的方法?
- abort():终止当前请求,一般配合abort事件一起使用
- setRequestHeader(头部字段的名,头部字段的值):设置一个请求头信息,只能设置极个别的字段
- POST方式下
- Content-Type:内容类型字段,告诉服务器,浏览器发送的数据是什么格式的
- POST方式下
3.XHR的事件?
- xhr.onload:load事件,响应数据可用时触发(IE6~IE8不兼容)
- xhr.onerror:error事件,请求发生错误时触发(IE10兼容)
- xhr.onabort:调用abort()方法时触发(IE10兼容)
- xhr.ontimeout:请求超时的时候触发(IE8开始支持)
4.AJAX进阶
4.1FormData
1.如何使用AJAX提交表单?
-
let login=document.getElementById("login"); const url='https://www.imooc.com/api/http/search/suggest?words=js'; // 使用FormData遍历表单元素 let fdata= new FormData(login); // 可以遍历出表单传过来的name以及对应的value for(let item of fdata){ console.log(item); } // 单击事件 let btn=document.getElementById("btn"); btn.onclick=(e)=>{ // 组织默认行为,不让它提交了,自己写行为 e.preventDefault(); // 表单数据验证 // 发送AJAX请求 const xhr=new XMLHttpRequest(); xhr.onload=function(){ if(xhr.readyState!==4) return; if(xhr.status>=200&&xhr.status<=299||xhr.status==304){ console.log(xhr.responseText); } } xhr.open("POST",url,true); xhr.send(fdata); }
2.FormData的基本用法?
- 通过HTML表单元素创建FormData对象
- const fd=new ForData(表单元素);
- xhr.send(fd);
- 通过 append()方法添加数据
- fd.append(‘age’,18);
4.2封装AJAX
4.3AJAX实现搜索提示
4.4axios
1.什么是axios?
- axios是一个机遇Promise的Http库,可以用在浏览器和node.js中
- 第三方Ajax库
- 官方网址:http://www.axios-js.com/zh-cn/docs/
2.axios的基本用法?
- 引入axios
- 用法和封装的方法相似
<!-- 第一步:引入axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const url='http://www.imooc.com/api/http/json/search/suggest?words=js';
//第一个参数:JSON请求地址
//第二个参数:请求的详细配置对象
axios(url,{
method:'post',
// 请求的头信息
header:{
// ' Content-Type':'application/JSON';
},
//通过请求头携带的数据
params:{
username:'ales'
},
// 通过请求体携带的数据
data:{
age:18,
sex:"male"
}
}).then(response=>{
console.log(response);
}).catch(reject=>{
console.log(reject);
})
</script>
5.Fetch
1.Fetch是什么?
- Fetch也是基于前后端通信的一种方式
- Fetch是Ajax(XMLHttpRequest)的一种替代品,它是基于Promise的
- Ajax的兼容性好
- Fetch没有abort也没有timeout
2.fetch的使用?
-
fetch(url)是一个函数,能够直接调用
-
fetch(url)执行的结果返回的是一个对象
-
fetch获取数据属性:
- body/bodyUsed
- body存放数据,body只能读一次,读过之后bodyUsed就等于true了,就不让再读了
- status:状态码
- statusText:状态码文字说明
- ok:数据是否获取成功,成功为true,失败为false
- response.json():获取json格式的结果数据
- resopnse.text():获取字符串类型的结果数据
- body/bodyUsed
-
fetch有两个参数:
- 第一个参数:请求地址
- 第二个参数:一个对象,配置fetch
- method:指定请求方式
- body:给请求体传数据,直接通过.toString()转换,如果传的数据是对象,需要先通过JSON.parse()
- headers:
- ‘Content-Type’: