JavaScript学习笔记(五)---cookie、Proxy、服务器、PHP语言、http协议、同步异步、事件轮循机制、ajax编写、接口
1.cookie
1.1cookie概念
- cookie是一个可以在页面间共享传递数据的变量。
cookie称为会话跟踪技术
会话session:一个网页APP从打开到完全关闭的过程,称为一次会话
cookie在会话期间可以在页面间共享传递数据
2.实现长生命周期的保存用户信息,实现免登录
1.2cookie读写
写:document.cookie="键=值";
读:console.log(document.cookie);
注意事项:cookie的使用必须有服务器
// 写
// document.cookie = "键=值";
// document.cookie = "name=翻翻";
document.cookie = "age=18";
document.cookie = "name=峰峰";
document.cookie = "gender=M";
// 读
// 通过分号和空格分开的字符串
//age=18; name=峰峰; gender=M
console.log(document.cookie);
// 实现字符串解析,获取每个key后面对应的value
let strCookie = document.cookie;
let arrCookie = strCookie.split(";");//["age=18","name=峰峰","gender=M"]
for (let i = 0; i < arrCookie.length; i++) {
let item = arrCookie[i].split("=");
console.log("key:" + item[0], "value:" + item[1]);
}
1.3页面传递数据案例
<body>
<button>点击</button>
</body>
</html>
<script>
let oBtn = document.querySelector("button");
oBtn.onclick = function () {
document.cookie = "name=翻翻";
document.cookie = "age=32";
location.href = "4.cookie页面传递数据02.html";
}
</script>
<script>
console.log(document.cookie);
</script>
1.4cookie的生命周期
会话级别:document.cookie = "键 = 值";
长生命周期:document.cookie = "name=laowang;expires="+date;
<script>
// 会话级别
// document.cookie = "键=值";
document.cookie = "key1=value1";
// 长生命周期
let date = new Date();
date.setDate(date.getDate() + 10);
document.cookie = "name=laowang;expires="+date;
</script>
1.5cookie的删除
cookie没有正面删除,只能侧面删除
1.将key对应的value设置为’ ’
2.将expires设置为-1(将长生命周期的cookie过期)
合起来一起用
document.cookie = "name='';expires=-1";
<script>
// cookie没有正面删除,只能侧面删除
// a.将key对应的value设置为''
// b.将expires设置为-1(将长生命周期的cookie过期)
// 合起来一起用
// document.cookie = "name='';expires=-1";
</script>
1.6cookie的封装
<script>
// 增改
function setCookie(key, value, day) {
if (day == undefined) {
document.cookie = `${key}=${value}`;
} else {
let date = new Date();
date.setDate(date.getDate() + day);
console.log(date);
document.cookie = `${key}=${value};expires=${date}`;
}
}
setCookie("name", "laowang");//会话
setCookie("age", 18, 7);
// 查
//
function getCookie(key) {
let strCookie = document.cookie;
let arrCookie = strCookie.split(";");
for (let i = 0; i < arrCookie.length; i++) {
let item = arrCookie[i].split("=");
if (item[0] == key) {
return item[1];
}
}
return '';
}
// console.log(getCookie("name"));
// 删 针对长生命周期
function deleteCookie(key) {
setCookie(key, '', -1);
}
deleteCookie("age");
</script>
1.7七天免登录
主页
<body>
用户名:<input type="text"><br />
密码:<input type="password"><br />
<select name="" id="">
<option value="0">无需免登录</option>
<option value="7">7天免登录</option>
<option value="30">30天免登录</option>
</select>
<button>登录</button>
</body>
</html>
<script src="cookie.js"></script>
<script>
if (getCookie("id") != '' && getCookie("pwd") != '') {
location.href = 'ok.html';
} else {
// 获取输入框
let oInput = document.getElementsByTagName("input");
// 获取下拉框的值
let oSelect = document.querySelector("select");
// 获取点击按钮
let oBtn = document.querySelector("button");
switch (oSelect.value) {
case '0':
break;
case '7':
case '30':
setCookie("id", oInput[0].value.oSelect.value / 1);
setCookie("pwd", oInput[0].value.oSelect.value / 1);
break;
}
location.href = "ok.html";
}
</script>
跳转后的页面
<body>
登陆成功!
</body>
封装的cookie
// 增改
function setCookie(key, value, day) {
if (day == undefined) {
document.cookie = `${key}=${value}`;
} else {
let date = new Date();
date.setDate(date.getDate() + day);
document.cookie = `${key}=${value};expires=${date}`;
}
}
// 查
function getCookie(key) {
let strCookie = document.cookie;
let arrCookie = strCookie.split("; ");
for (let i = 0; i < arrCookie.length; i++) {
let item = arrCookie[i].split("=");
if (item[0] == key) {
return item[1];
}
}
return '';
}
// 删 针对于长生命周期
function deleteCookie(key) {
setCookie(key, '', -1);
}
2.本地及会话存储
localStorage和sessionStorage功能早期的web中使用cookies在客户端保存诸如用户名等简单的信息,但是在使用cookies存储永久数据存在以下问题:
- cookies的大小限制在4kB,不适合大量的数据存储。
- 浏览器还限制站点可以在用户计算机上存储cookies的数量。
- cookies是随http事务一起被发送的,因此会浪费一部分宽带。
- cookies的原生API贼难用。HTML5很好的提供了本地存储的功能,以键值对存储的解决方案,支持容量至少为4M~5M,HTML5的web提供了两种客户端存储方法。
localStorage:是一种没有时间限制的数据存储方式,可以将数据永久保存在客户端。
sessionStorage:指的是针对一个session的数据存储,即将数据保存在session对象中,当关闭浏览器后,这些数据就被删除。因此,sessionSetorage不是一种持久化的本地存储,仅仅是会话级别的存储。
2.1localStorage和sessioonStorage都具有相同的操作方法,都是单例模式
getItem(key):获取指定key所存储的value值
key(index)方法:返回列表中对应索引的key值
length属性:返回key/value队列的长度
removeItem(key)方法:从Storage中删除一个对应的键值对。
setItem(key,value)方法:将value存储到key指定的字段。
clear()方法:移除所有的内容
// 增改
// a.setItem("key","value")
localStorage.setItem("name", "老王");
// sessionStorage.setItem("age", 18);
// b.点运算符
// localStorage.age = 18;
// c.下标法
localStorage["gender"] = "M";
localStorage.setItem("name", "凡凡")
// 查
// a.getItem("key"):返回key对应的value
console.log(localStorage.getItem("name"));
// b.点运算符
console.log(localStorage.age);
// c.下标法
console.log(localStorage["gender"]);
// 删
// removeItem("key"):删除key对应的value
localStorage.removeItem("name");
localStorage.removeItem("age");
localStorage.clear();
// key(index)方法:返回列表中对应索引的key值
// length属性:返回key/value队列的长度
for(let i = 0 ; i<localStorage.length;i++){
console.log(localStorage.getItem(localStorage.key(i)));
}
可以存储数组或者对象
localStorage.setItem("data", '{"name":"老王","age":18}');
// 将字符串转为JSON对象
console.log(localStorage.data);
let json = JSON.parse(localStorage.getItem("data"));
console.log(json.name,json.age);
页面关闭时触发:
// 页面关闭时触发,
window.onbeforeunload = function () {
localStorage.setItem("GoodsInfor", '{"goodsName"="苹果","goodsNum":9}');
}
console.log(localStorage.getItem("GoodsInfor"));
3.object.defineproperty
vue2双向绑定原理
通常创建一个对象的方法
let json = {
"name": "老王",
"age": 18
}
delete json.name;
for(let index in json){
console.log(index);
}
console.log(json.name,json.age);
3.1defineProperty作用
defineProperty作用:就是直接在一个对象上定义一个新属性,或者修改删除一个已经存在的属性,
通过Object.defineProperty( )定义属性,通过描述符的设置可以进行更精准的控制对象属性。
语法:Object.defineProperty (目标对象,属性名,属性描述符对象)
基础属性描述符
- value: 18,//属性的名字
- configurable: true,//该属性是否可以被delete删除
- enumerable: true,//该属性是否可以被forin遍历出来
- writable: true//该属性是否可以被修改
let stu = {
"name": "老王"
}
stu.age = 18;
Object.defineProperty(stu, "age", {
// 基础属性描述符
value: 18,//属性的名字
configurable: true,//该属性是否可以被delete删除
enumerable: true,//该属性是否可以被forin遍历出来
writable: true//该属性是否可以被修改
});
delete stu.age;
stu.age = 999;
console.log(stu.age);
for(let index in stu){
console.log(index);
}
除了以上基础描述符外,最重要的两个描述符函数get和set
// 除了以上基础描述符外,最重要的两个描述符函数get和set
let stu = {
"name": "老王",
"age": 18
}
// 时间点:当对象进行读写操作时,可以被Object.defineProperty拦截,
// 也就是说,在读写的过程中,要经过Object.defineProperty检测
Object.defineProperty(stu, 'name', {
// 为什么属性名需要加_,为了避免递归
set: function (v) {
console.log("haha");
// 很复杂的代码块
if (v > 10) {
this._name = v;
} else {
this._name = "数据不正确";
}
},
get: function () {
console.log("hiehie");
return this._name;
}
})
// 注意事项:在使用get和set修饰符时,不要和基础修饰符连用,否则会报错
// 写
stu.name = 5;
// 读
console.log(stu.name);
3.2vue2双向绑定原理
操作数据就等于操作dom
数据驱动思想,通过修改数据渲染页面,而不是直接操作dom
<script>
// vue2双向绑定原理
// 操作数据就等于操作dom
let data = {
"name": "老王"
}
let oBox = document.querySelector("#box");
Object.defineProperty(data, "name", {
set: function (v) {
oBox.innerHTML = v;
},
get: function () {
this._name = oBox.innerHTML;
return this._name;
}
});
data.name = "小明";
console.log(data.name);
// 数据驱动思想,通过修改数据渲染页面,而不是直接操作dom
</script>
4.Proxy
Vue3绑定原理,核心问题还是拦截对象属性的读写
proxy(代理)是一个对象
为什么需要代理对象?目标对象的某些功能无法实现
let p = new Proxy(目标对象,修饰符对象);
let stu = {
"name": "老王",
fun: function () {
console.log(this);
}
}
// 通过p对象代理stu,也就是说操作p等价于操作stu
let p = new Proxy(stu, {});
p.name = "嘿嘿";
console.log(stu.name, p.name);
// this代理对象的this问题?
// 目标对象调用成员方法,this为目标对象
// 代理对象调用成员方法,this为代理对象
stu.fun();
p.fun();
5.hanOwnProperty
用来判断某个属性是否属于自身,不去遍历原型链
let arr = [1, 2, 3];
Object.prototype.a = 666;
arr.b = 999;
console.log(arr.a);
console.log(arr.b);
console.log(arr.hasOwnProperty("a"));//false,原型对象不是数组本身的元素
console.log(arr.hasOwnProperty("b"));//true
let json = {
a: 1
}
// 原型对象只是构造函数的一个属性
Object.prototype.b = 666;
// 遍历的是自身及父元素原型对象的属性
// for (let index in json) {
// console.log(index);//a b
// }
// 只遍历自身的属性不包含继承来的属性
for (let index in json) {
if (json.hasOwnProperty(index)) {
console.log(index);
}
}
6.服务器
C/S架构:客户机/服务器结构
B/S架构:浏览器/服务器结构
服务器是用来处理前后端数据交互的软件
服务器的分类:
- web服务器:可以让用户在外网访问到自身服务器
- 数据库服务器:存储数据的服务器
服务器有很多种:
- web服务器,apache,nodejs,tomcat
- 数据库服务器,mySql,oracle,sqlServer,mongodb
apache服务器是phpstudy软件自带的
apache使用方式,安装phpstudy(不能安装到桌面),启动后当apache显示绿色则服务器启动成功,我们只需要将文件放入WWW目录(开发目录的代码拷贝至部署目录),则可访问
外界就可以通过:
- F:\htmlTest\server\WWW 等价于 ip地址
- ip地址+文件名的方式访问
环形地址:代表本机IP的字符串或者地址
- 127.0.0.1
- localhost
注意事项:部署目录中不要出现中文
7.PHP语言
外文名PHP:Hypertext Preprocessor,中文名:“超文本预处理器”是一种通用开源脚本语言。语法吸收了C语言、java和Perl的特点,利于学习,使用广泛,主要适用于web开发领域。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。
-
文件扩展名:php
-
代码写在
<?php?>
之间 -
PHP代码每句话以分号结束(必须)
-
编码格式:
header("Content-type:text/html;charset=utf-8");
<?php
// echo目前等价于document.write
// php除了可以做后端文件外,还能当html页面显示(通常没有人这么干)
// 支持中文
header("Content-type:text/html;charset=utf-8");
// echo "hello php";
// echo "老王";
// 1.php变量的定义
// $name = "小明";
// $age = 18;
// php字符串拼接用点
// echo $name . " " . $age;
// 2.if分支条件
// $a = 123;
// $b = 456;
// if($a >$b){
// $c = $a ;
// }else{
// $c = $b;
// }
// echo $c;
// 3.数组与循环
$arr = [6,5,7,4,8,3];
// count数组的长度
for($i=0;$i<count($arr);$i++){
echo $arr[$i]." ";
}
// 4.函数
function fun($a,$b){
return $a>$b?$a:$b;
}
echo fun(1,2);
// 注意事项:千万不要忘记分号
?>
8.PHP接收前端的数据
表单中:
- action:数据发送的服务器文件
- method:数据提交的方式(默认不写为get)
- get:效率高,安全性低,将数据携带在网址后面,携带数据量小
- post:效率低,安全性高,携带数据量大
- name:前后端的约定
html文件:
<body>
<!--
action:数据发送的服务器文件
method:数据提交的方式(默认不写为get)
get:效率高,安全性低,将数据携带在网址后面,携带数据量小
post:效率低,安全性高,携带数据量大
name:前后端的约定
-->
<form action="http://127.0.0.1:80/day27/4.login.php" method="post">
ID:<input type="text" name="userName"><br>
PWD:<input type="text" name="userPwd"><br>
<input type="submit" value="登录">
</form>
</body>
PHP接收前端的数据:
* PHP接收前端的数据
* $_POST[‘参数名’]
* $_GET[“参数名”]
* $_REQUEST[“参数名”];
<?php
header("Content-type:text/html;charset=utf-8");
// 接收前端数据
// * PHP接收前端的数据
// * $_POST['参数名']
// * $_GET["参数名"]
// * $_REQUEST["参数名"];
// $name = $_GET['userName'];
// $pwd = $_GET['userPwd'];
$name = $_POST['userName'];
$pwd = $_POST['userPwd'];
// 1.php变量的定义
$name = "小明";
$age = 18;
// php字符串拼接用点
echo $name . " " . $age;
// $name = $_REQUEST['userName'];
// $pwd = $_REQUEST['userPwd'];
// echo $name." ".$ped;
?>
9.http协议
http协议:基于请求和响应的超文本传输协议
如何发请求:(访问服务器文件的规则格式)
-
完全体:http://127.0.0.1:80/day27/4.login.php
-
url地址构成
http:// ip地址 + 端口号 + 文件路径
ip地址:电脑在网络中的唯一识别符(相对于人的身份证号)
端口:标记了电脑上某一个软件的号码
如何接响应:前端只能被动接收响应数据
服务端除了响应数据外会返回一些状态码,告知前端交互情况
- 200 数据交互成功
- 404 你的url写错了
- 5XX 服务器的问题,请给后端告状
10.ajax概念及作用
前言:只要发送请求,浏览器就会刷新页面,因为后端返回数据后,浏览器要重新渲染页面
需求:局部更新(异步刷新)
- ajax(Asynchronous JavaScript And XML)技术打破了之前只要发请求就刷新页面的规则,
- AJAX是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
- 前端通过与服务器进行少量数据交换,AJAX可以使网页实现异步更新。这意味着可以在不重新加载整个页面的情况下,对网页的某部分进行更新
为什么要使用AJAX
- 更自然,流畅的用户体验,对用户的操作即时响应
- 在不中断用户操作的情况下web服务器进行通信
- 更灵敏的响应用户访问,实现近似于桌面应用程序的交互效果
- 通过局部更新页面降低网络流量,提高网络的使用效率
11.同步和异步
- 异步代码的特点:所有的代码都需要消耗执行时间,而异步代码除了消耗执行时间外,还需要消耗等待时间
- 同步执行方式:代码按照顺序一步一步执行,前一步没有执行完,后一步无法执行
- 异步执行方式:代码在遇到需要消耗等待时间的代码时,先跳过该代码执行后续代码
异步代码的父类:和消耗时间有关的代码都是异步代码
- 定时器的回调函数
- 事件体
- 发请求和接响应
当同步代码与异步代码同时存在时,优先执行同步代码,在根据异步消耗的时间,执行异步代码只有同步代码遵循自上而下的执行规则,异步和消耗等待的时间有关
<script>
// 1.买菜
// 2.洗菜
// 3.切菜
// 4.烧水
// 5.炒菜
// 异步代码的特点:所有的代码都需要消耗执行时间,而异步代码除了消耗执行时间外,还
// 需要消耗等待时间
// 同步执行方式:代码按照顺序一步一步执行,前一步没有执行完,后一步无法执行
// 异步执行方式:代码在遇到需要消耗等待时间的代码时,先跳过该代码执行后续代码
// 异步代码的父类:和消耗时间有关的代码都是异步代码
// a.定时器的回调函数
// b.事件体
// oBtn,onclick = function () {
// console.log("嘿嘿");//事件体是异步代码
// }
// c.发请求和接响应
// console.log(1);
// setInterval(function () {
// console.log(2);
// }, 0);
// setInterval(function () {
// console.log(3);
// }, 0);
// setInterval(function () {
// console.log(4);
// }, 0);
// console.log(5);
// 当同步代码与异步代码同时存在时,优先执行同步代码,在根据异步消耗的时间,执行异步代码
// 只有同步代码遵循自上而下的执行规则,异步和消耗等待的时间有关
let time = setInterval(function () {
console.log("heihei");
}, 1000);
// 属于同步代码
clearInterval(time);
</script>
12.事件轮循机制
12.1事件循环
事件循环是什么?为什么要有事件循环这个东西?
我们都知道js是单线程的,但是像Ajax,或者是事件这种很耗时的操作,需要用并发处理,否则单线程会长时间等待,什么也做不了。而事件循环就是并发的一种形式,一个线程中只有一个事件循环。而任务队列是用来配合事件循环完成操作的,一个线程可以拥有多个任务队列
12.2任务队列
所谓任务是webAPIs返回的一个个通知,让js主线程在读取任务队列的时候得知这个异步任务已经完成,下一步该执行这个任务的回调函数了。主线程拥有多个任务队列,不同的任务队列用来排列来自不同任务源的任务。
任务源是什么?
像setTimeout/Promise/DOM 事件等都是任务源,来自同类任务源的任务我们称它们是同源的,比如setTimeout与setInterval就是同源的。 在es6标准中任务队列又分为宏观任务队列和微观任务队列
12.3任务
所有任务可以分两种:一种是同步任务(synchronous) ,另一种是异步任务(asynchronous) 。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;//执行栈
异步任务指的是,不先进入主线程,而进入"任务队列"(task queue) 的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。
12.4执行顺序
- 先执行同步代码
- 当异步代码结束等待状态,进入准备执行状态,通知主线程
- 当主线程的同步代码执行完毕时,执行异步代码
- 重复以上三步
13.ajax编写步骤
1.创建XMLHttpRequest对象
let xhr = new XMLHttpRequest();
2.调用open方法(规划请求)
xhr.open("get/post忽略大小写","服务器文件地址",是否异步);
3.send(真实发送请求)post的请求参数通过send发送
xhr.send([请求参数]);
4.onreadystatechange事件(异步)
onreadystatechange事件是由readyState属性发生改变而触发的,但是只有2~4的改变会触发该事件
0:刚创建完xhr对象
1:调用完OPEN方法
2.请求发送出去
3.请求发送到了服务器
4.请求数据完成解析,可以进行响应
status:
// 200 代表协议顺利,数据交互完成
// 404 网址写错了
// 5xx 服务器问题
xhr.onreadystatechange = function () {
// status == 200; 电话打通了,嘟嘟嘟
// readyState == 4:人家接通了电话
if (xhr.status == 200 && xhr.readyState == 4) {
// 5.回复你响应 --->xhr.responseText
fun(xhr.responseText);
}
}
function fun(resText) {
// console.log(resText);
let p = document.querySelector("p");
p.innerHTML = resText;
}
<body>
<div>哈哈哈</div>
<button>发送</button>
<p></p>
</body>
</html>
<script>
let oBtn = document.querySelector("button");
oBtn.onclick = function () {
// 1.掏手机 ---> 创建XMLHttpRequest对象
let xhr = new XMLHttpRequest();
// 2.拨号 ---> 调用open方法
// xhr.open(请求方式,服务器地址,true);
xhr.open("get", "02.txt", true);
// 3.发射 ---> send
xhr.send();
// 4.等 ---> onreadystatechange事件(异步)
xhr.onreadystatechange = function () {
// status == 200; 电话打通了,嘟嘟嘟
// readyState == 4:人家接通了电话
if (xhr.status == 200 && xhr.readyState == 4) {
// 5.回复你响应 --->xhr.responseText
fun(xhr.responseText);
}
}
}
function fun(resText) {
// console.log(resText);
let p = document.querySelector("p");
p.innerHTML = resText;
}
</script>
13.1ajaxGet
html文件
<body>
<input type="text"><span></span>
</body>
</html>
<script>
let oInput = document.querySelector("input");
let oSpan = document.querySelector("span");
oInput.onblur = function () {
let xhr = new XMLHttpRequest();
// url?key1=value1&key2=value2....
// form表单和ajax都是发请求给后端,两个不能重复,等于说以前的事是浏览器干现在在是你干
// userName就是form表单中input的name属性的值
xhr.open("GET", "03.ajacGet.php?userName" + this.value, true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
fun(xhr.responseText);//所有的操作都是为了获取响应内容
}
}
}
function fun(resText) {
oSpan.innerHTML = resText;
}
</script>
php文件
<?php
header("Content-type:text/html;charset=utf-8");
$name = $_GET["userNamer"];
// 模拟数据库
$arr = ["峰峰","凡凡","小明","小米"];
// in_array(查找的目标元素,数组);找到返回下标,没找到返回空
if(in_array($name,$arr)){
// php在参与ajax的过程中,echo的作用为返回响应
each '用户名已经存在';
}else{
echo '可以注册';
}
<?php
header("Content-type:text/html;charset=utf-8");
$name = $_GET["userNamer"];
// 模拟数据库
$arr = ["峰峰","凡凡","小明","小米"];
// in_array(查找的目标元素,数组);找到返回下标,没找到返回空
if(in_array($name,$arr)){
// php在参与ajax的过程中,echo的作用为返回响应
each '用户名已经存在';
}else{
echo '可以注册';
}
?>
13.2ajax对象属性
<script>
// 创建XMLHttpRequest对象
let xhr = new XMLHttpRequest();
// xhr.open("get/post忽略大小写","服务器文件地址",是否异步);
console.log(xhr.readyState);
// get的请求参数携带在url
xhr.open("get", "02.txt", true);
console.log(xhr.readyState);
// post的请求参数通过send发送
// xhr.send([请求参数])
xhr.send();
// onreadystatechange事件是由readyState属性发生改变而触发的,但是只有2~4的改变会触发该事件
// 0:刚创建完xhr对象
// 1:调用完OPEN方法
// 2.请求发送出去
// 3.请求发送到了服务器
// 4.请求数据完成解析,可以进行响应
xhr.onreadystatechange = function () {
// status:
// 200 代表协议顺利,数据交互完成
// 404 网址写错了
// 5xx 服务器问题
// console.log(xhr.responseText);
if (xhr.readyState == 4 && xhr.status == 200) {
// 接收的响应内容
console.log(xhr.responseText);
}
}
</script>
13.3ajaxPost
与get的不同点:
1.请在open和send之间,设置请求头,将数据以form表单post形式发送
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
2.将请求参数通过send发送
key1=value1&key2=value2…
xhr.send(
userName=${this.value});
html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text"><span></span>
</body>
</html>
<script>
let oInput = document.querySelector("input");
let oSpan = document.querySelector("span");
oInput.onblur = function () {
let xhr = new XMLHttpRequest();
xhr.open("post", "05.ajaxPost.php", true);
// 1.请在open和send之间,设置请求头
// 将数据以form表单post形式发送
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
// 2.将请求参数通过send发送
// key1=value1&key2=value2...
xhr.send(`userName=${this.value}`);
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
fun(xhr.responseText);//所有的操作都是为了获取响应内容
}
}
}
function fun(resText) {
// 前后端分离,
// 前端主要实现页面渲染
// 后端尽可能少实现描述性数据
if (resText == "1") {
oSpan.innerHTML = "好了";
} else if (resText == "0") {
oSpan.innerHTML = "不好了";
}
}
</script>
php文件
<?php
header("Content-type:text/html;charset=utf-8");
$name = $_POST["userName"];
//模拟数据库
$arr = ["凢凢","峰峰","翔翔","波波"];
//in_array(查找的目标元素,数组);找到返回下标,没找到返回空
if(in_array($name,$arr)){
//php在参与ajax的过程中,echo的作用为返回响应
// echo '用户名已经存在';
echo "1";
}else{
// echo '可以注册';
echo "0";
}
?>
13.4php返回json
html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul></ul>
</body>
</html>
<script>
let xhr = new XMLHttpRequest();
xhr.open("get", "06.phpReturnJson.php", true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
fun(xhr.responseText);
}
}
function fun(resText) {
// console.log(resText);
let json = JSON.parse(resText);
let oUl = document.querySelector("ul");
for (let index in json) {
oUl.innerHTML += `<li>${json[index]}</li>`;
}
}
</script>
php文件
<?php
header("Content-type:text/html;charset=utf-8");
//1.直接返回json字符串
// echo '{"1":"美羊羊","2":"洋了个洋","3":"狗了个狗"}';
//2.通过数组转换json字符串
$arr = ["A"=>"喜羊羊","B"=>"洋了个洋","C"=>"狗了个狗"];
//将$arr转为json字符串
echo json_encode($arr);
?>
14.ajax关注并加载案例
该案例得在服务器apache下运行
html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div></div>
<button>关注并加载更多</button>
</body>
</html>
<script src="ajax.js"></script>
<script>
let oDiv = document.querySelector("div");
let oBtn = document.querySelector("button");
function getNews(page) {
// let xhr = new XMLHttpRequest();
// xhr.open("get", "1.getNews.php?page=" + page, true);
// xhr.send();
// xhr.onreadystatechange = function () {
// if (xhr.readyState == 4 && xhr.status == 200) {
// fun(xhr.responseText);
// }
// }
ajax("1.getNews.php", "get", "page=" + page, fun);
}
getNews(1);
oBtn.onclick = function () {
getNews(2);
this.style.display = "none";
}
function fun(resText) {
console.log(resText);
oDiv.innerHTML += resText;
}
</script>
php文件
<?php
header("content-type:text/html;charset=utf-8");
$page = $_GET["page"];
if($page == 1){
echo "我感觉";
}else if($page == 2){
echo "还好。";
}
?>
ajax封装的js文件
function ajax(url, type, data, callBack) {
let xhr = new XMLHttpRequest();
type = type.toLowerCase();
if (type == "get") {
let urlParam = url;
// 有参
if (data != "") {
urlParam += "?" + data;
}
xhr.open(type, urlParam, true);
xhr.send();
} else {
xhr.open(type, url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 有参
if (data != "") {
xhr.send(data);
} else {
xhr.send();
}
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
callBack(xhr.responseText);
}
}
}
15.接口
接口概念:后端提供的服务器文件地址,通过这些文件地址,可以发送请求获取响应内容
访问接口的四要素:
- 接口文件地址
- 发送请求方式 get/post
- 请求参数
- 响应数据内容
16.ajax封装
html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<script>
// url:请求地址
// type:请求方式:get/post
// data:请求参数:key1=value1&key2=value2 无参""
// callBack:接收响应的回调函数
function ajax(url, type, data, callBack) {
let xhr = new XMLHttpRequest();
type = type.toLowerCase();
if (type == "get") {
let urlParam = url;
// 有参
if (data != "") {
urlParam += "?" + data;
}
xhr.open(type, urlParam, true);
xhr.send();
} else {
xhr.open(type, url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 有参
if (data != "") {
xhr.send(data);
} else {
xhr.send();
}
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
callBack(xhr.responseText);
}
}
}
ajax("3.myAjax.php", "GET", "name=老王&pwd=666", fun);
function fun(resText) {
console.log(resText);
}
</script>
php文件
<?php
header("content-type:text/html;charset=utf-8");
$name = $_REQUEST["name"];
$pwd = $_REQUEST["pwd"];
echo $name . " " .$pwd;
?>
17.promise
需求:当函数嵌套过多就会形成回调地狱,多级异步操作的回调函数嵌套
如何优化回调地狱?
promise概念:是一个对象,是专门用来处理异步操作的容器
promise作用:promise是处理异步操作的一种方式,通过promise可以将函数嵌套调用的方式,改为平级调用,最常用于发请求和接响应
语法规则:
let p = new Promise(function(接收响应成功的函数,[接收响应失败的函数]){
// 该回调函数就是包裹异步操作的容器
});
promise对象在使用的时候函数需要返回promise对象
以前的回调函数是通过promise对象的then方式传递的,promise对象.then(接收成功响应的函数,[接收失败响应的函数])
<script>
// function f1(f) {
// console.log("f1");
// f();
// }
// function f2(f) {
// console.log("f2");
// f();
// }
// function f3() {
// console.log("f3");
// }
// f1(f3);
// 这样的写法是错误的,函数f3当做函数f2的形参传入f2中调用
// 而f2后面有括号可以理解为f2已经被调用了,所以f1中传入的就是
// f2函数调用后的返回值,而实际上f1需要传进去的参数应该是
// 一个函数,导致程序出现错误。
// f1(f2(f3));
// 给已经被调用的f2的外侧加一个匿名函数就可以保证传给f1的是
// 一个函数
// f1(function () {
// f2(f3);
// })
// ---------------------
// function f1(f) {
// console.log("f1");
// f();
// }
// function f2(f) {
// console.log("f2");
// f();
// }
// function f3(f) {
// console.log("f3");
// f();
// }
// function f4() {
// console.log("f4");
// }
// // // 回调地狱,其实就是回调函数嵌套过多导致
// f1(function () {
// f2(function () {
// f3(f4);
// });
// });
// 围绕着该重点理解
// ajax(第一个请求,function(第一个响应)){
// ajax(第二个请求,第一个响应作为请求参数,function(第二个响应)){
// ajax(第三个请求,第二个响应作为请求参数,function(第三个响应)){
// }
// }
// }
// 有的就有好几个请求嵌套,第一个请求响应后的回复响应的数据要作为第二个请求响应的参数
// 发生第二次请求,第二次请求响应后得到的数据要进行作为第三个请求的参数
// 如何优化回调地狱?
// promise概念:
// promise是一个对象,是专门用来处理异步操作的容器
// promise的作用:
// promise是处理异步操作的一种方式,通过promise可以将函数嵌套调用的方式,改为平级调用
// 最常用于发请求和接响应
// let p = new Promise(function(接收响应成功的函数,[接收响应失败的函数]){
// // 该回调函数就是包裹异步操作的容器
// });
// function f1(f) {//不能再让回调函数通过参数传递了
// console.log("f1");
// f("成功的响应")
// }
// function f2(resText) {
// console.log(resText);
// }
// f1(f2);
// ----------------------------------
// function f1() {
// console.log("f1");
// let p = new Promise(function (f2) {
// f2("成功接收的响应");
// });
// return p;
// }
// function f2(resText) {
// console.log(resText);
// }
// // 以前的回调函数是通过promise对象的then方法传递的
// // promise对象.then(接收成功响应的函数,[接收失败响应的函数])
// f1().then(f2);
function f1() {
console.log("f1");
let p = new Promise(function (f) {
f();
});
return p;
}
function f2() {
console.log("f2");
let p = new Promise(function (f) {
f();
});
return p;
}
function f3() {
console.log("f3");
let p = new Promise(function (f) {
f();
});
return p;
}
function f4() {
console.log("f4");
}
f1().then(f2).then(f3).then(f4);
</script>
17.1promise案例
场景1:异步操作过程中,比如f2发送请求需要依赖于f1的响应,f3发送请求依赖于f2的响应,
这就意味着异步代码必须以同步的方式按顺序执行,
解决方案:将f2写在f1的回调,将f3写在f2的回调,代价就是回调地狱
初步解决方案promise,可以将函数嵌套调用改为平级调用
场景2:同时发送若干请求,需要所有请求都完成响应后再渲染页面
Promise.all([请求1,请求2…]).then(resText=>{
});
当哪个请求失败了全部失败必须要全部完成响应
场景3:往往需要的到的响应内容,不是只有一个接口的,可以同时发送多个请求,哪个响应快用哪个
Promise.race([p1,p2,p3]).then(resText=>{
})
<script>
// 场景1:异步操作过程中,比如f2发送请求需要依赖于f1的响应,f3发送请求依赖于f2的响应,
// 这就意味着异步代码必须以同步的方式按顺序执行,
// 解决方案:将f2写在f1的回调,将f3写在f2的回调,代价就是回调地狱
// 初步解决方案promise,可以将函数嵌套调用改为平级调用
// let x = f1();
// let y = f2(x);
// f3(y);
// 场景2:同时发送若干请求,需要所有请求都完成响应后再渲染页面
// Promise.all([请求1,请求2...]).then(resText=>{
// });
// 当哪个请求失败了全部失败必须要全部完成响应
// let p1 = new Promise(function (success, failed) {
// // setInterval(function () {
// // success("p1的响应");
// // }, 1000);
// setInterval(function () {
// failed("失败了");
// }, 1000);
// });
// let p2 = new Promise(function (success) {
// setInterval(function () {
// success("p2的响应");
// }, 500);
// })
// let p3 = new Promise(function (success) {
// setInterval(function () {
// success("p3的响应");
// }, 2000);
// })
// Promise.all([p1, p2, p3]).then(resText => {
// console.log(resText);
// })
// 场景3:
// 往往需要的到的响应内容,不是只有一个接口的,可以同时发送多个请求,哪个响应快用哪个
// Promise.race([p1,p2,p3]).then(resText=>{
// })
let p1 = new Promise(function (success, failed) {
setInterval(function () {
success("p1的响应");
}, 1000);
});
let p2 = new Promise(function (success) {
setInterval(function () {
success("p2的响应");
}, 500);
})
let p3 = new Promise(function (success) {
setInterval(function () {
success("p3的响应");
}, 2000);
});
Promise.race([p1, p2, p3]).then(resText => {
console.log(resText);
});
</script>
18.async和awite
async专门用来修饰异步函数的关键字
当某个函数被async修饰时,则返回携带响应内容的Promise对象
注意事项:async wait的作用是用来等待异步方法的响应结果
并且await只能出现在async修饰的方法中
<script>
// async专门用来修饰异步函数的关键字
// 当某个函数被async修饰时,则返回携带响应内容的Promise对象
// function f1() {
// return new Promise(function (success) {
// success("嘿嘿");
// });
// }
// 和上述代码的返回值相同都是Promise {<fulfilled>: undefined}
// async function f1() {
// return "嘿嘿";
// }
// console.log(f1());
// --------------------------
// async function f1() {
// return "heihei";
// }
// // 注意事项:async wait的作用是用来等待异步方法的响应结果
// // 并且await只能出现在async修饰的方法中
// async function f() {
// let resText1 = await f1();
// console.log(resText1);
// }
// console.log(f());
// 上述代码执行过程,先调用函数f()执行函数f(),函数f()中先执行await关键字后面
// 的函数调用f1(),进入函数f1()并返回返回携带响应内容的Promise对象,将响应内容
// 赋给resText1,打印出来。
// ----------------------------
// async function f1() {
// // return "heihei";
// return new Promise(function (success) {
// setTimeout(function () {
// success("嘿嘿");
// }, 1000);
// });
// }
// async function f() {
// let resText1 = await f1();
// console.log(resText1);
// }
// console.log(f());
// 上述代码的执行过程:
// 函数f1先被调用,执行函数f1的时候先执行await后的调用函数f1
// 函数f1被调用并返回携带响应数据的Promise对象
// 将携带的数据赋给变量resText1,并输出
// ---------------------
async function f1() {
return new Promise(function (success) {
setTimeout(function () {
success("p1的响应");
}, 1000);
});
}
async function f2(param) {
console.log(param + "哈哈");
return new Promise(function (success) {
setTimeout(function () {
success("p2的响应");
}, 500);
});
}
async function f3(param) {
console.log(param + "嘤嘤嘤");
return new Promise(function (success) {
setTimeout(function () {
success("p3的响应");
}, 2000);
});
}
async function fun() {
let resText1 = await f1();
console.log(resText1);
let resText2 = await f2(resText1);
console.log(resText2);
let resText3 = await f3(resText2);
console.log(resText3);
}
fun();
</script>
19.跨域访问
跨域:跨域名访问,网站A页面访问网站B服务器上的文件
但是由于浏览器的安全机制同源策略,不允许跨域访问
同源策略:同IP,同协议,同端口
No ‘Access-Control-Allow-Origin’(不允许跨域访问)
前端跨域:
jsonp:是前端一种跨域的技术
如何实现跨域?
- src属性是可以跨域的
- script标签拥有src属性,可以访问远程文件
- 前后端约定函数名,前端写函数定义,后端写函数调用
注意事项:jsonp只支持get,所以只能通过get方式发送请求参数
后端跨域:
cors
header(“Access-Control-Allow-Origin:*”);
<body>
<!-- <img src="http://10.48.183.118/1.jpg" alt=""> -->
<img src="http://10.48.183.100/3.jpg" alt="">
</body>
</html>
<script>
// 跨域:跨域名访问,网站A页面访问网站服务器上的文件
// 但是由于浏览器的安全机制同源策略,不允许跨域访问
// 同源策略:同IP,同协议,同端口
let xhr = new XMLHttpRequest();
xhr.open("get", 'http://10.48.183.118/2.php', true)
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
fun(xhr.responseText);
}
}
function fun(resText) {
console.log(resText);
}
// No 'Access-Control-Allow-Origin'
// 不允许跨域访问
// -------------------------
// 前端跨越:
// jsonp:是前端一种跨越的技巧
// 如何实现跨域?
// 1.src属性是可以跨域的
// 2.script标签拥有src属性,可以访问远程文件
// 3.前后端约定函数名,前端写函数定义,后端写函数调用
// 注意事项:
// jsonp只支持get,所以只能通过get方式发送请求参数
function fun(resText) {
console.log(resText);
}
// fun("马上十一了嘿嘿嘿");
// 后端跨域:
// cors
// header("Access-Control-Allow-Origin:*");
</script>
<!-- <script src="http://10.48.183.118/1.txt"></script> -->
<!-- <script src="http://10.48.183.118/2.php"></script> -->
20.真百度搜索框
<body>
<input type="text">
<ul></ul>
</body>
</html>
<script>
// 接口四要素
// 1.接口地址
// http://suggestion.baidu.com/su
// 2.请求方式
// get
// 3.请求参数
// wd:搜索的关键字
// cb:传递后端的函数名
// 4.返回的响应内容
// {
// q:"迪丽热巴",
// p:false,
// s:[
// "迪丽热巴演的电视剧",
// "迪丽热巴个人所有资料",
// "迪丽热巴男朋友",
// "迪丽热巴照片",
// "迪丽热巴微博",
// "迪丽热巴代言的品牌有哪些",
// "迪丽热巴肚子上怎么有妊娠纹",
// "迪丽热巴金主",
// "迪丽热巴身材",
// "迪丽热巴体重"
// ]
// }
let oInput = document.querySelector("input");
let oUl = document.querySelector("ul");
oInput.oninput = function () {
if (this.value != "") {
let oScript = document.createElement("script");
document.body.appendChild(oScript);
oScript.src = `http://suggestion.baidu.com/su?wd=${this.value}&cb=fun`;
} else {
oUl.innerHTML = "";
}
}
function fun(resText) {
oUl.innerHTML = "";
for (let i = 0; i < resText.s.length; i++) {
oUl.innerHTML += `<li>${resText.s[i]}</li>`;
}
}
</script>