JavaScript学习笔记(五)---cookie、Proxy、服务器、PHP语言、http协议、同步异步、事件轮循机制、ajax编写、接口

1.cookie

1.1cookie概念
  1. 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存储永久数据存在以下问题:

  1. cookies的大小限制在4kB,不适合大量的数据存储。
  2. 浏览器还限制站点可以在用户计算机上存储cookies的数量。
  3. cookies是随http事务一起被发送的,因此会浪费一部分宽带。
  4. 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还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。

  1. 文件扩展名:php

  2. 代码写在<?php?>之间

  3. PHP代码每句话以分号结束(必须)

  4. 编码格式:

    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.同步和异步

  1. 异步代码的特点:所有的代码都需要消耗执行时间,而异步代码除了消耗执行时间外,还需要消耗等待时间
  2. 同步执行方式:代码按照顺序一步一步执行,前一步没有执行完,后一步无法执行
  3. 异步执行方式:代码在遇到需要消耗等待时间的代码时,先跳过该代码执行后续代码

异步代码的父类:和消耗时间有关的代码都是异步代码

  1. 定时器的回调函数
  2. 事件体
  3. 发请求和接响应

当同步代码与异步代码同时存在时,优先执行同步代码,在根据异步消耗的时间,执行异步代码只有同步代码遵循自上而下的执行规则,异步和消耗等待的时间有关

<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执行顺序
  1. 先执行同步代码
  2. 当异步代码结束等待状态,进入准备执行状态,通知主线程
  3. 当主线程的同步代码执行完毕时,执行异步代码
  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.接口

接口概念:后端提供的服务器文件地址,通过这些文件地址,可以发送请求获取响应内容

访问接口的四要素:

  1. 接口文件地址
  2. 发送请求方式 get/post
  3. 请求参数
  4. 响应数据内容

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:是前端一种跨域的技术

如何实现跨域?

  1. src属性是可以跨域的
  2. script标签拥有src属性,可以访问远程文件
  3. 前后端约定函数名,前端写函数定义,后端写函数调用

注意事项: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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值