JavaScript-0905-ajax的封装和cookie

1、响应
    响应行
        状态码属于http协议中规定,通过使用数字表示出响应的状态
        在数据交互时使用的code状态码与http协议中状态码没有关系。code属于后端规定的数字来表示某种含义
    响应头
        属于服务端通知客户端的自身信息
    空白行
    响应体
2、Ajax概述
    ajax属于异步代码
    使用场景:需要数据时
    使用步骤
        1、获取对象 new XMLHttpRequest
        2、打开连接  xhr.open(请求方式,请求URL地址)
        3、发送请求 xhr.send(请求体参数)
        4、监听状态改变 xhr.onload = function(){}
3、Ajax内置的属性方法
    readyState:表示ajax对象的状态0 表示实例化对象 1、表示打开了连接2、表示请求已经发送 3、表示请求响应过程中 4、表示响应完成
    responseText 响应文本
    status:http协议的状态码
    onreadystatechange:  readyState状态改变自动触发的处理程序
3、ajax发送不同方式请求
    get请求 一般参数在URL地址上 ?参数1=1&参数2=2....
    post:参数在请求体中 需要根据服务端要求的数据格式设置请求头content-type
    
    
ajax代码的错误写法    
    
    let content = '';
    发送请求
    xhr.onload = function(){
        content = xhr.responseText
    }
    开始使用content变量  由于Ajax异步的 所以绝对content是空字符串
---
typora-root-url: img
---

# 复习回调函数

将A函数作为参数传递给B函数使用,最终B函数将A函数调用起来就将A叫做回调函数。

回调函数使用场景是当自己封装函数时,某些功能无法实现(如果直接使用代码就让功能固定,但是功能又不能缺

少)就可以使用回调函数,将具体要做的功能交给调用者来决定

例如数组中forEach方法确实将数组中每一个元素都会取出来所以设置了回调函数让调用者决定每个元素该如何处理

1、函数本质

```javascript
每次创建一个函数就是在内存中会开辟对应的存储空间
function fn(){}
栈区创建fn变量 将函数代码存储到堆区 并且将 堆区的地址保存在fn变量的栈区
所以每次使用一个函数都是得到的是内存地址(注意区分函数调用)
fn:取到函数的内存地址 
fn()取到函数调用return的结果

2、函数传递数组

// 栈区存储的arr变量保存的是堆区的地址(内存地址) 假设内存地址为0X111
let arr = [1,2,3]

function fn(a){
    // a = 0X111

}
// 等价于 fn(0X111)
fn(arr)

3、将函数作为参数

 // 等价于 let callbaclk = 0X222;
function callback(){
    console.log('callback')
}


function fn(a){
    // a=0X222 a变量与callback这个变量指向到同一个堆区地址,所以a()
}
// fn(0X222)
fn(callback)

4、回调函数简写

function fn(a){

        }
        // 只要书写了function函数 就得到一个内存地址 所以这句话就是调用fn函数 并且将内存地址传递了
        fn(function(){})

5、回调函数使用参数

function fn(a){
    let option = {name:'张三','age':20};
    // 调用函数传递实参
    a(option)
}
// 因为 fn函数执行时a(option)  调用函数 所以将匿名函数运行起来 并且传递了实参 所以 就会存在let opc = option
fn(function(opc){
    console.log(opc)
})

Ajax封装

1、处理参数问题

/**
 * 发送Ajax请求的函数
 * @param {Object} options 表示请求控制的对象 其中每个属性名称有自己的含义并且为固定的含义 type表示请求方式,url表示请求地址、data表示请求参数、contentType表示请求头Content-Type、headers表示额外的请求头、dataType表示返回结果 success 表示成功的回调函数 
 */
function ajax(options){
    // 1、设置默认配置
    let config = {
        type:'get',
        url:'',
        data:'',//可以支持字符串、也可以支持对象
        contentType:'application/json',
        headers:{},
        dataType:'json',
        success:function(){}
    }
    // 2、配置合并
    for(let key in options){
        // 检查用户传递的options对象下是否存在需要的属性,如果存在就覆盖否则就忽略
        (options[key] != undefined) && (config[key] = options[key])
    }
}

2、验证请求方式

// 3、参数验证
    // 3.1、验证请求方式 要求请求方式只能是get、post、put、delete
    // 先将请求方式统一转换为小写
    config.type = config.type.toLowerCase();
    // 验证请求方式
    if(!['get','post','put','delete'].includes(config.type)){
        throw new Error('请求方式不容许')
    }

3、验证url

// 3.2、验证URL 验证url必须是字符串并且 不能是空
    if(Object.prototype.toString.call(config.url) !='[object String]' || !config.url ){
        throw new Error('请求url错误')
    }

4、验证contentType

// 3.3、验证contentType 只验证两种值
    if(config.contentType != 'application/json' && config.contentType != 'application/x-www-form-urlencoded'){
        throw new Error('contentType头信息错误');
    }

5、headers验证

// 3.4、验证headers 要求必须是对象格式
if(Object.prototype.toString.call(config.headers) != '[object Object]'){
throw new Error('请求头格式错误');
}

6、success验证

// 3.5、success必须要求是函数
    if(Object.prototype.toString.call(config.success) != '[object Function]'){
        throw new Error('请求头格式错误');
    }

7、请求参数校验

// 3.6、data必须是字符串或者对象格式
// 提取请求参数的类型
let requestDataType = Object.prototype.toString.call(config.data);
// 验证请求参数
if( requestDataType != '[object String]' && requestDataType != '[object Object]'){
    throw new Error('请求参数错误');
}

8、组装url地址

// 4、组装请求的url地址
    // 保存请求URL地址的变量
    let url = config.url;
   
    // 如果是get或者delete请求 将参数组装到url变量中
    if(config.type == 'get' || config.type == 'delete'){
        if(requestDataType == '[object String]'){
            url +='?'+config.data;
        }else{
            // 表示请求参数为对象 将参数转换为字符串格式
            url+='?';
            for(let key in config.data){
                url += `${key}=${config.data[key]}&`
            }
            // 去掉字符串中最后的一个&
            url = url.slice(0,-1);
        }  
    }

9、设置请求头

    // 5、获取Ajax对象
    let xhr = new XMLHttpRequest;
    // 6、打开连接
    xhr.open(config.type,url);
    // 7、设置请求头
    xhr.setRequestHeader('Content-Type',config.contentType);
    for(let key in config.headers){
        xhr.setRequestHeader(key,config.headers[key]);
    }

10、发送请求

// 8、发送请求
    let requestBody = null;
    if(config.type == 'post' || config.type == 'put'){
        if(requestDataType == '[object String]'){
            requestBody = config.data;
        }else{
            // data参数表示为对象格式 就需要转换为表单格式或者JSON格式
            if(config.contentType == 'application/json'){
                requestBody = JSON.stringify(config.data);
            }else{
                requestBody='';
                for(let key in config.data){
                    requestBody += `${key}=${config.data[key]}&`
                }
                // 去掉字符串中最后的一个&
                requestBody = requestBody.slice(0,-1);
            }
        }
    }
    xhr.send(requestBody);

11、处理结果

// 9、处理结果
    xhr.onload = function(){
        // 判断服务端如果返回的是JSON格式就转换为对象 否则就是字符串
        let response = (config.dataType=='json')?JSON.parse(xhr.responseText):xhr.responseText
        // 得到服务端的结果之后处理方式不确定
        config.success(response);
    }

案例

实现注册功能

<!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>
    <link rel="stylesheet" href="./layui/css/layui.css">
    <script src="./layui/layui.js"></script>
    <style>
        #one,
        html,
        body {
            width: 100%;
            height: 100%;
            background: rgba(119, 136, 153, 0.3);
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #two {
            width: 400px;
            height: 300px;
            border: 2px solid black;
            border-radius: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
            position: relative;
        }

        #tishi {
            width: 120px;
            height: 20px;
            position: absolute;
            top: 130px;
            left: 160px;
            display: none;
            background: pink;
            font-size: 12px;
            text-align: center;
            line-height: 20px;
        }

        button {
            margin-top: 20px;
        }
    </style>
</head>

<body>
    <div class="layui-container">
        <div class="layui-row">
            <div class="layui-col-xs6  layui-col-sm6 layui-col-md6 layui-col-lg6">
                
               
                    <div class="layui-form-item">
                        <label class="layui-form-label">手机号</label>
                        <div class="layui-input-block">
                            <input type="text" required lay-verify="required" placeholder="请输入手机号" autocomplete="off"
                                class="layui-input" id="name">
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <label class="layui-form-label">密码</label>
                        <div class="layui-input-block">
                            <input type="text" required lay-verify="required" placeholder="请输入密码" autocomplete="off"
                                class="layui-input" id="password">
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <div class="layui-input-block">
                            <button class="layui-btn" lay-submit lay-filter="formDemo">立即注册</button>

                        </div>
                    </div>
                
            </div>
        </div>


    </div>



</body>

</html>
<script src="../common.js"></script>
<script>
    document.querySelector('button').addEventListener('click', () => {
        let mobile = document.querySelector('#name').value;
        let password = document.querySelector('#password').value;
        ajax({
            url: 'http://phpclub.org.cn/edu/server/regist.php',
            type: 'post',
            contentType: 'application/x-www-form-urlencoded',
            data: {
                mobile,
                password
            },
            success: function (backData) {
                if(backData.code!=100){
                    layer.msg(backData.msg,{icon:4});
                    return;
                }
                location.href = 'login.html';
            }
        });
    })
</script>

实现用户登录

1、封装获取元素的函数

/**
 * 匹配页面元素
 * @param {String} elem css选择器规则
 * @param {Boolean} hasMore 是否返回集合
 * @returns 
 */
function $$(elem,hasMore=false){
    return hasMore==false?document.querySelector(elem):document.querySelectorAll(elem);
}

2、实现登录

<!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>
    <link rel="stylesheet" href="./layui/css/layui.css">
    <script src="./layui/layui.js"></script>
</head>

<body>
    <div class="layui-container">
        <div class="layui-row">
            <div class="layui-col-md4 ">
                <div class="layui-card">
                    <div class="layui-card-header"><strong>用户登录</strong></div>
                    <div class="layui-card-body">
                        <input type="text" class="mobile layui-input" placeholder="输入手机号">
                        <br />
                        <input type="text" class="password layui-input" placeholder="输入密码">
                        <br />
                        <button class="layui-btn layui-btn-normal">登录</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
</body>

</html>
<script src="../common.js"></script>
<script>
    $$('button').onclick = function(){
        let mobile = $$('.mobile').value;
        let password = $$('.password').value;
        ajax({
            url:'http://phpclub.org.cn/edu/server/login.php',
            type:'post',
            data:{mobile,password},
            contentType:'application/x-www-form-urlencoded',
            success: function(backData){
                if(backData.code != 100){
                    layer.msg(backData.msg,{icon:5});
                    return;
                }
                // 代码执行到这一行说明目前的账号信息是正常的
                location.href = 'index.html'
            }
        });
    }
</script>

cookie

cookie介绍

cookie是属于一种本地的存储技术,cookie的实现与http协议存在关系。

可以将cookie理解为本地客户端的存在介质,可以将数据保存在浏览器上(浏览器在控制到客户端文件)。并且是以

域名为基准

cookie属于键值对格式,并且可以设置有效时间。cookie使用场景只有一个,就是实现免登陆功能

在这里插入图片描述

cookie的使用

设置cookie

1、设置cookie

 // 设置cookie
        // 1、语法  有效路径一般使用/表示整个域名下的文件都可以使用 有效时间默认是关闭浏览器失效,也可以设置为具体的过期时间(需要设置的是标准的格林威治时间)  设置值的时候只能设置为字符串格式如果设置为其他类型会自动的调用toString方法转换
        // document.cookie = '名称=值;path=有效路径;expires=有效时间';
        document.cookie='userId=9527';

2、访问查看效果
在这里插入图片描述

3、继续访问
在这里插入图片描述

4、设置cookie的有效时间

// 2、设置cookie的有效时间
let d = new Date;
// 以当前时间计算出1分钟之后的格林威治时间
let time = d.getTime()+60*1000 - 8*3600*1000;
d.setTime(time);
document.cookie='userId=9527;path=/;expires='+d;

读取cookie

1、获取cookie

console.log(document.cookie)

2、结果
在这里插入图片描述

删除cookie

1、语法

docuemnt.cookie='名称=值;expires=过期的时间'

2、实现删除cookie

let d = new Date;
// d.getTime() - 8*3600*1000 计算当前的格林威治时间 减掉某一个数字 就是一个过期的时间
let time = d.getTime() - 8*3600*1000-1000;
d.setTime(time);
document.cookie='nickname=喝脉动吃鸡煲;path=/;expires='+d

cookie的封装

1、封装设置cookie的函数

/**
 * 设置cookie
 * @param {String} key cookie的名称 
 * @param {String|Object} value cookie的值
 * @param {Number} expires 有效时间 表示过期的秒数 0表示关闭浏览器失效
 */
function setCookie(key, value, expires = 0) {
    // 为了让使用者方便 传递非字符串格式就转换为JSON格式
    value = Object.prototype.toString.call(value) == '[object String]' ? value : JSON.stringify(value);
    if (expires == 0) {
        // 表示关闭浏览器失效
        document.cookie = `${key}=${value};path=/`;
        return;
    }
    // 具备有效时间
    let d = new Date;
    // 以当前时间计算出1分钟之后的格林威治时间
    let time = d.getTime() + expires * 1000 - 8 * 3600 * 1000;
    d.setTime(time);
    document.cookie = `${key}=${value};path=/;expires=${d}`;
}

2、删除cookie

/**
 * 删除cookie
 * @param {String} key 要被删除cookie的名称 
 */
function removeCookie(key){
    setCookie(key,'',-1);
}

3、获取cookie

/**
 * 获取指定名称的cookie
 * @param {String} key 
 */
function getCookie(key){
    let value = undefined;
    document.cookie.split('; ').forEach(item=>{
        let keyValue = item.split('=');
        if(keyValue[0] == key){
            value = keyValue[1];
        }
    })
    try {
        return JSON.parse(value);
    } catch (error) {
        return value;
    }
}

使用cookie解决登录问题

1、修改登录逻辑
在这里插入图片描述

2、实现首页

<!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>
    <strong class="mobile">XXX</strong>你好 <a href="javascript:;" class="logout">退出</a>
    <hr class="layui-border-red">
</body>
</html>
<script src="../common.js"></script>
<script>
    // 获取到cookie中内容  如果能够取出结果为对象 否则就是undefined
    // 如果cookie中有值就证明已经登录 否则就是未登录
    let userInfo = getCookie('userInfo');
    if(userInfo){
        $$('.mobile').innerHTML = userInfo.mobile;
    }
    // 实现退出
    $$('.logout').onclick = function(){
        removeCookie('userInfo');
        location.reload();
    }
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

goto_w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值