Ajax笔记

%title插图%num
请求方式

$.get()请求

%title插图%num

该请求方式一般用于请求数据,通常用于获取服务端资源

// 参数:(资源地址,[请求期间要携带的参数], [请求成功的回调函数]);
$.get (url,[data],[callback]);

参数名 参数类型 是否必选 说明
url string 提交数据的地址
data object 要提交的数据
callback function 数据提交成功时的回调函数
dataType string 规定预期的服务器响应的数据类型,默认会自行判断。可自行手动定义。
“xml”、”html”、”text”、”script”、”json”、”jsonp”

$.post()请求

%title插图%num

该请求方式一般用于提交数据,通常用于向服务器提交数据

// 参数:(资源地址,[请求期间要携带的参数], [请求成功的回调函数]);
$.post (url,[data],[callback]);

参数名 参数类型 是否必选 说明
url string 提交数据的地址
data object 要提交的数据
callback function 数据提交成功时的回调函数
dataType string 规定预期的服务器响应的数据类型,默认会自行判断。可自行手动定义。
“xml”、”html”、”text”、”script”、”json”、”jsonp”

$.ajax()请求

相比 $.get() 和 $.post() 函数,jQuery中提供的 $.ajax() 函数是一个功能比较综合的函数,它允许我们对ajax请求进行更详细的配置

注意:是以对象方式传入参数 详细参数介绍可查阅 CSDN文档

// 请求的方式 请求的地址 携带的数据 回调函数
$.ajax ({type:”,url:”,data:{},success:function(res){}})

参数名 参数类型 是否必选 说明
{method} string 请求的方式:如 GET 或 POST
{url} string 请求的URL地址
{data} object 请求携带的数据
{success} function 请求成功之后的回调函数
{dataType} string 规定预期的服务器响应的数据类型,默认会自行判断。可自行手动定义。
“xml”、”html”、”text”、”script”、”json”、”jsonp”
{error} function 请求失败的回调函数,有三个参数 XMLHttpRequest, textStatus, errorThrown
{beforeSend} function 在发送请求之前调用,如果返回false可以取消本次ajax请求
{complete} function 请求完成后调用的回调函数(请求成功或失败时均调用)

示例:

       $(function () {
            // 发起 ajax 请求
            $.ajax({
                //请求类型 GET
                method: ‘GET’,
                // 请求的 url 地址
                url: ‘http://www.liulongbin.top:3006/api/getbooks’,
                // 请求需要携带的数据
                data: { id: 1 },
                // 回调函数 将结果 res 返回
                success: function (res) {
                    console.log(res);
                }
            })
        })

xhr.abort() 中断请求

如果用户频繁点击ajax请求,有两个问题:

1. 如果连续点击了5个ajax请求,前4个其实是无效的,趁早结束节省资源。
2. 更严重的问题是:最后一个发送的请求,响应未必是最后一个,有可能造成混乱。还需要一个队列来维护发送的请求和响应

Let ajaxGet = $.get(“comet_server.php”,{id:1},function(data){
…. // 一些操作
});
// 中断请求 $.post 与 $.ajax 同理
ajaxGet.abort();

$.ajaxPrefilter() 前置过滤器

每当发起 ajax 请求时,都会预先调用该函数

在所有参数选项被jQuery.ajax()函数处理之前,你可以使用该函数设置的回调函数来预先更改任何参数选项。
>> 下面是制作公共 url 地址的方式

$.ajaxPrefilter(function (options) {
    // 项目的请求根路径
    let url = ‘http://www.liulongbin.top:3007’;
    // 每次请求进行拼接
    options.url = url + options.url;
});

接口的概念

案例体验:图书管理系统

使用AJax请求数据时,被请求的URL地址,就叫做数据接口,同时,每个接口必须有请求方式。例如:

// GET 用于获取图书列表的接口
http://www.liulongbin.top:3006/api/getbooks
// POST 用于添加图书的接口
http://www.liulongbin.top:3006/api/addbook
// GET 用于删除图书的接口
http://www.liulongbin.top:3006/api/delbook

案例体验:一言播报

使用了网络上一言的接口,获得接口传来的文字时并以参数形式发送给网络上音频的接口。并将得到的音频数据发送给 一个隐藏的 <audio>标签,并设置自动播放 autoplay 参数

// GET 直接获取一言
https://api.uixsj.cn/hitokoto/get
// GET 识别参数 text 文字并返回音频 status
http://www.liulongbin.top:3006/api/synthesize

jQuery 表单处理

表单主要用于数据采集功能,HTML中的 <from> 标签,就是用于采集用户输入的信息,并通过 <form> 标签的提交操作。把采集到的信息提交到服务器端进行处理。

<!– 让表单同步提交方式 提交数据 会 跳转页面 且造成界面刷新 丢失数据 用户体验很差 –>
<form action=”目标地址”>
        <input type=”text” name=”user”> // name和name的值会被记录,通过某些形式发送给目标地址
        <input type=”password” name=”pass”>
        <button type=”submit”>发送</button> // submit 事件会直接执行提交
    </form>

.submit() 监听表单提交事件

在 jQuery 中,可以使用如下两种方式,监听到表单的提交事件

 // 事件绑定方式 
$(‘#bd’).submit(function () {
       alert(‘监听到了提交事件’);
});
// on 多事件绑定方式
 $(‘#bd’).on(‘submit‘, function () {
      alert(‘监听到了提交事件’);
});

serialize() 获取表单提交内容

在使用 e.preventDefault() 阻止默认事件后,单击 submit 按钮时将不再进行提交。这时候 ajax 接手表单接收和传送的操作

            $(‘#bd’).submit(function (e) { 
              e.preventDefault();
                let str = $(this).serialize();
                $.post(”, str, function (res) {
                    …
                }); 
          });

案例体验:发表评论

使用了接口实现评论的自由存储,并采用 原生js的 .reset() 函数重置表单内容

// GET 评论接收接口 +content [内容] +time [发布时间] +username [发布人]
http://www.liulongbin.top:3006/api/cmtlist
// POST 评论发布接口 +username [发布人] +content [内容]
http://www.liulongbin.top:3006/api/addcmt

jQuery 模板引擎

art-template 模型引擎

模型引擎是为了使布局更清晰,减少字符串的拼接,易于后期维护和调整

art-template 官方文档

引用模型引擎

  <script src=”../jquery.js”></script>
  <script src=”../template-web.js”></script>
// 模板会在 参数1(结构) + 参数2(数据) 拼接一个 HTML结构的字符串
template(filename, data);

模板放置位置 template( 模板目标 ,数据目标 ); 会根据 id 或者 class 找到下方模板目标,但引用不用加 # 或 .

     <script type=”text/html” id=”data-mod”>
<p>{{data.name}}</p>

     </script>

标准语法 数据将最终放置在花括号 {{value}} 里

{{value}}
{{data.key}}
{{data[‘key’]}}
{{a ? b : c}}
{{a || b}}
{{a + b}}

条件判断 类似 if else

   {{if value}} … {{/if}}
   {{if v1}} … {{else if value}} … {{/if}}

循环语句 使里面的值根据 target数组的长度进行循环遍历 {{ $index }}为循环下标 {{ $value }} 为循环的值

   {{each target}}
   {{$index}} {{$value}}
   {{/each}}

过滤器 template.defaults.imports.xxx 会将数据里 {{ name }} 引用的值传给过滤器处理,最终由过滤器输出结果

   <span>{{$value.time | 变量函数名}}</span>
   template.defaults.imports.变量函数名 = function(date, format){/*[code..]*/};

案例演示新闻列表

正则表达式

.exec() 正则表达式匹配

正则表达式 类似于通配符的增强版,帮你匹配指定字符的字符串,可在 正则表达式测试 体验
关于更多正则知识 可访问 r2coding

%title插图%num

exec() 函数用于 检索字符串 中的正则表达式的匹配,如果字符串中有匹配的值,则返回该匹配值,否则返回 null

        let str = ‘你好HTML’;
        let pattern = /L/;
        let result = pattern.exec(str);
        console.log(result); // [‘L’, index: 5, input: ‘你好HTML’, groups: undefined]

多次使用 exec() 函数 正则遍历 exec() 使用 设定的正则表达式 实现找到{{}}内的字母,并使用whlie循环查找,而exec()找不到目标返回为null,使用 replace() 方法去掉字符串的所有{{}},当 exec() 无法找到后结束 while 循环

      // 定义数组对象
        let data = {name:’zs’,user:’smm’};
        // 定义一串字符
        let str = ‘{{name}}—-{{user}}’;
        // 定义正则表达式 /匹配{{}}内所有字母和字母两侧空格/ 的方法赋值给 pattern
        let pattern = /{{\s*([a-zA-Z]+)\s*}}/;
        // 初始化 result
        let result = null;
        // 循环操作 将正则表达式匹配的结果以对象方式返回给变量 直到 result 找不到 返回 null
        while (result = pattern.exec(str)) {
            // str 替换 正则表达式匹配的 内容 目的为去掉 {{}}
            str = str.replace(result[0],  data[result[1]);
        }
        // 结果 name—-user 已提取
        console.log(str);

test() 方法用于检测一个字符串是否匹配某个模式

let str=’你好 JavaScript’;
let pattern=/S/;
console.log(pattern.test(str)); // true

art-template 模型引擎核心实现原理

        let data={name:’smm’,age:22}
        // 使用 whlie 循环 replace 目的为 替换多个花括号的值
        let str3='<div>大家好我是{{name}},我今年{{age}}岁了</div>’;
        // 正则表达式 /匹配{{}}内所有字母和字母两侧空格/ 的方法 赋值给变量 pattern3
        let pattern3=/{{\s*([a-zA-Z]+)\s*}}/;
        // 初始化 将 null 赋值给 result4
        let result4=null;
        // 循环操作 将正则表达式匹配的结果以对象方式返回给变量 直到 result4 找不到 返回 null
        while(result4=pattern3.exec(str3)){
            // str3 替换 data对象中 同名成员的值
            str3=str3.replace(result4[0],data[result4[1]]);
        }

模型案例 试着输入art-template结构的 html ,左侧会生成HTML模型样式


【data数据】

let data={name:’张三’,age:66,jop:’程序员’,img:’/图片’}


XMLHttpRequest

XMLHttpRequest 原生接口请求

%title插图%num

XMLHttpRequest (简称:xhr) 是浏览器提供的 JavaScript对象,通过它,可以请求服务器上的数据资源,jQuery的 ajax 函数,就是基于 xhr 对象封装出来的

xhr对象 readyState属性

该属性用来表示当前 ajax 请求所处状态。每个 ajax 请求必然出于以下状态中一个

状态 描述
0 UNSENT XMLHttpRequest 对象已创建
1 OPENED open() 方法已经被调用
2 HEADERS_RECEIVED send()方法已经被调用,响应头已经被接收
3 LOADING 数据接收中,此时 response 属性已经包含部分数据
4 DONE ajax 请求完成,意味着数据传输已经彻底 完成 或 失败

使用 xhr 发起 GET 请求

        // 1.创建 xhr 对象
        let xhr = new XMLHttpRequest();
        // 2.调用 open 函数
        xhr.open(‘GET’, ‘http://www.liulongbin.top:3006/api/getbooks’);
        // 3.调用 send 函数 发起 ajax 请求
        xhr.send();
        // 4.监听 onreadystatechange 事件
        xhr.onreadystatechange = function () {
            // 4.1 [固定写法] 监听 xhr 对象的请求状态 readyState && 与服务器响应的状态 status
            if (xhr.readyState === 4 && xhr.status === 200) {
                // 4.2 打印 服务器 响应 回来的数据
                console.log(xhr.responseText);
            }
        }

使用 xhr 发起带参数的 GET 请求

使用 xhr 对象发起带参数请求时,只需在调用 xhr.open 期间,为URL后面 ? 指定参数即可,多个参数用 & 隔开

        // 2.调用 open 函数 并传入参数 id:1
        xhr.open(‘GET’, ‘http://www.liulongbin.top:3006/api/getbooks?id=1‘);

使用 xhr 发起带参数的 POST 请求

send() 填入参数,并以查询字符串方式传入至服务器,

        // 1.创建 xhr 对象
        let xhr = new XMLHttpRequest();
        // 2.调用 open 函数
        xhr.open(‘POST’, ‘http://www.liulongbin.top:3006/api/addbook’);
        // 3.[固定写法]设置 Content-Type 属性
        xhr.setRequestHeader(‘Content-Type‘, ‘application/x-www-form-urlencoded‘);
        // 4.调用 send() 并将数据以查询字符串形式 提交给服务器
        xhr.send(‘bookname=哲学&author=比利海灵顿&publisher=新日暮里出版社’);
        // 5.监听 onreadystatechange 事件
        xhr.onreadystatechange = function () {
            // 5.1 监听 xhr 对象的请求状态 readyState && 与服务器响应的状态 status
            if (xhr.readyState === 4 && xhr.status === 200) {
                // 5.2 打印 服务器 响应 回来的数据
                console.log(xhr.responseText);
            }
        }

封装自己的ajax函数

模仿 jQuery 的 $.ajax() 函数,实际去写一个自己的 ajax 函数

// 拼接查询字符函数
function resolveData(data) {
    let arr = [];
    for (let k in data) {
        let str = k + ‘=’ + data[k];
        arr.push(str);
    }
    return arr.join(‘&’);
}
function myAjax(options) {
    //实例化 XML 对象
    let xhr = new XMLHttpRequest();
    // 将用户传入的 data对象 转换成 查询字符串 赋值给 qs
    let qs = resolveData(options.data);
    // 判断用户请求的方式 GET [toUpperCase()用于转换为大写字母]
    if (options.type.toUpperCase() === ‘GET’) {
        // 发起 GET 请求 并 拼接 查询字符
        xhr.open(options.type, options.url + ‘?’ + qs);
        xhr.send();
        // 判断用户请求的方式 POST [toUpperCase()用于转换为大写字母]
    } else if (options.type.toUpperCase() === “POST”) {
        // 发起 POST 请求
        xhr.open(options.type, options.url);
        // [固定写法]设置 Content-Type 属性
        xhr.setRequestHeader(‘Content-Type‘, ‘application/x-www-form-urlencoded‘);
        xhr.send(qs);
    }
    // 回调函数 返回服务器响应的数据 并将 数据的 JSON字符串 进行转换成 JS对象并赋值给 success 成员
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
            let result = JSON.parse(xhr.responseText);
            // 定义 success为方法 并输入参数 result
            options.success(result);
        }
    }}

Level 新特性

timeout 可以设置HTTP请求时限 (单位:毫秒)

xhr.timeout = 3000

ontimeout 可以设置超时后的回调函数 (单位:毫秒)

// 超时处理函数
xhr.ontimeout = function () {
  console.log(‘请求超时’);
}

formData 文件上传

FormData 对象管理表单数据 (ajax操作往往用来提交表单数据,该 新增对象 可以方便表单处理,模拟表单操作 ,该表单数据用于 POST请求)

        // 新建 FormData 对象
        let fd = new FormData();
        // 调用 append 函数 为 FormData 追加数据
        fd.append(‘uname’, ‘zs’);
        fd.append(‘upwd’, ‘123456’);
        // 创建 XHR 对象 
      let xhr = new XMLHttpRequest();
        // 指定请求类型与URL地址
        xhr.open(‘POST’, ‘http://www.liulongbin.top:3006/api/formdata’);
        // 提交 表单数据 与 <form>表单数据提交 效果一致
        xhr.send(fd);
        // 监听回调函数
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                // 服务器响应回来的数据 转换成 Js对象
                console.log(JSON.parse(xhr.responseText));
            }
        }

formData 对象表单数据 还可以自动接收表单填入的数据 (绑定后,就无需程序员手动 append() 操作了)

        form.addEventListener(‘submit’,function(e){
          // 阻止 表单事件 的 默认行为 (禁止默认提交)
          e.preventDefault();
          // 根据 form表单 创建 formData对象 会自动将表单数据 填充到 FormData对象 中
          let fd=new FormData(form);
          …
        });

document.filesfiles 可获取用户上传文件队列的数组 并因此 files.length 可用于验证用户是否选择了文件

        // 绑定元素
        let btn = document.querySelector(‘#btnUpLoad’);
        // 按钮事件监听 单击事件
        btn.addEventListener(‘click’, function () {
            // 获取 选择的 文件列表 数组
            let files = document.querySelector(‘#file_1’).files;
            // 判断 用户 是否 上传文件
            if(files.length<=0){
                console.log(‘无文件内容’);
            }
        });

搭配 formData 实现向 formData 中追加文件

        btn.addEventListener(‘click’, function () {
            // 获取 选择的 文件列表
            let files = document.querySelector(‘#file_1’).files;
            // 实例化 表单数据对象 赋值给 fd
            let fd = new FormData();
            // 将数组 files下标 0 内容追加到 表单数据对象
            fd.append(‘file’, files[0]);
        }
);

upload.onprogress 事件 显示文件上传进度 (需要写在 send() 调用之前)

                // 监听 xhr.upload 的 onprogress 事件 (监听上传进度)
                xhr.upload.onprogress = function (e) {
                    // e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
                    if (e.lengthComputable) {
                        // e.loaded (已传输的字节) / e.total (需传输的总字节)
                        let precentComplete = Math.ceil((e.loaded / e.total) * 100);
                        console.log(precentComplete);
                    }
                }

upload.onload 事件 文件上传进度完成 (需要写在 send() 调用之前)

                // 监听 xhr.upload 的 onload 事件 (监听完成进度)
                xhr.upload.onload=function(){
                    // 执行的事件
                }

引入 Bootstrap 的CSS样式,实现进度条加载 模板官网链接

%title插图%num

    <!– 进度条 –>
    <div class=”progress” style=”width: 500px;margin: 15px;”>
        <div class=”progress-bar progress-bar-striped active” style=”width: 0%” id=”percent”>
        </div>
    </div>

// 动态改变 样式的内部滚动条长度 和内容信息
document.querySelector(‘#percent’).style.width = precentComplete + ‘%’;
document.querySelector(‘#percent’).innerHTML = precentComplete + ‘%’;

参考案例上传进度条

jQuery 实现文件上传

若需要上传文件的 固定写法中 contentTypeprocessData 两者属性皆为 false

在 ajax 中 contentType 设置为 false 是为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件

// 不修改 Content-Type 属性,使用FormData 默认的 Content-Type 值
contentType: false,
// 不对 FormData 中的数据进行 url编码,而是将 FormData 数据原样发送到服务器
processData: false,

ajaxStart() 方法会监听所有当前文档内 ajax请求。它是一个 Ajax 事件,ajaxStop() 同理,一个是 ajax上传事件 开始,一个是ajax上传事件结束。搭配使用可呈现显示 加载中 / 加载完成 效果

            // 文档中 ajax 请求事件响应
            $(document).ajaxStart(function () { })
            // 文档中 ajax 请求事件结束
            $(document).ajaxStop(function(){ })

URL 编码与解码

url地址中,只允许出现英文五相关的字母、标点符号、数字,因此在URL地址中不允许出现中文字符。如若URL中需要包括中文这样的字符,则必须对中文字符进行编码(转义)。

url 将 使用安全的字符,去表示那些不安全的字符 会自动对 字符进行编码,因此一般不需要对中文的传值进行处理

encodeURI() 编码 decodeURI() 解码

// 对非英文字符进行编码
encodeURI(‘屎猫猫’);
// 对编码进行解码
decodeURI(‘%E5%B1%8E%E7%8C%AB%E7%8C%AB’);

数据交换格式 XML JSON

数据交换格式,就是服务器端与客户端之间进行数据传输与交换的方式。

%title插图%num

常用的有 XML 和 JSON

XML

XML 的英文全称 EXtensible Markup Language (可扩展标记语言),因此,XML和HTML类似,也是一种标记语言,但是它俩无任何关系。XML被设计用来传输和存储数据,是数据的载体

缺点:XML格式臃肿,和数据无关的代码多,体积大,传输效率低

<node>
<!– 发送目标 –>
 <to>smm</to>
 <!– 来源 –>
 <from>aipo</from>
 <!– 标题 –>
 <heading>通知</heading>
 <!– 内容 –>
 <body>今天摸鱼</body>
</node>

JSON

JSON 的英文全称是 JavaScript Object Notation (对象表示法) 。它用于计算机与网络之间存储和传输数据,JSON 就是 JavaScript对象 和数组的字符串表示法,它使用文本表示一个 JS 对象或数组的信息。因此,JSON 的本质是字符串。它已经成为主流的数据交换格式

优点:JSON 是一种轻量级的文本数据交换格式,在作用上类似于XML,专门用于存储和传输数据,但是 JSON 比 XML 更小、更快、更易解析

[
    {
        “id”: 0,
        “name”: “smm”,
        “like”: “摸鱼”,
        “vip”: true
    },
    {
        “id”: 1,
        “name”: “AIPO”,
        “like”: “画画”,
        “vip”: true
    }]

JSON 的对象结构中表示为 {} 括号内的内容。数据结构为 { “key”:value… } 。其中,key必须使用英文的双引号包括的字符串,value 的数据类型 可以是 数字、字符串、布尔值、null、数组、对象 6种类型

JSON字符串 转换 js对象

【反序列化】要实现从 JSON字符串 转换成 JS对象,使用 JSON.parse() 方法

   let obj = JSON.parse(‘{“name”:”smm”,”like”:”摸鱼”}’);

【序列化】要实现从 JS对象 转换成 JSON字符串,使用 JSON.stringify() 方法

  let json = JSON.stringify({name:’smm’,like:’摸鱼’});

axios 库

Axios 是专注于网络数据请求的库,相比XML对象,axios简单易用。相比于jQuery更加轻量级。只专注于网络数据请求

GET请求语法

axios.get(” url “,{params:{ /* 参数 */ }}).then( callback 回调函数 );

示例:

        // 请求的地址
        let url=’http://www.liulongbin.top:3006/api/get’;
        // 请求的 参数对象
        let paramsObj={name:’zs’,age:20};
        // 调用 axios.get() 发起 GET 请求
        axios.get(url,{params:paramsObj}).then(function(res){
            // res包装了多个属性参数 其中 res.data 才是服务器返回的数据内容
            let result=res.data;
            console.log(result)
        });

POST请求语法

axios.post(” url “,{ /* 参数 */ }).then( callback 回调函数 );

示例:

            // 请求的地址
            let url=’http://www.liulongbin.top:3006/api/post’;
            // 要提交到服务器的数据
            let dataObj={location:’北京’,address:’昌平区’};
            // 调用 axios.post() 发起 POST 请求
            axios.post(url,dataObj).then(function(res){
            // res包装了多个属性参数 其中 res.data 才是服务器返回的数据内容
                let result=res.data;
                console.log(result);
            })

AXIOS 请求语法

该语法支持更多的请求方式,并可在对应的属性成员中传入参数用于发送到服务器

            axios({
                method:’GET’,
                url:’http://liulongbin.top:3006/api/getbooks’,
                // 发起 POST 请求的数据填在 data 中
                data:{},
                // 发起 GET 请求的数据填在 params 中
                params:{id:2},
            }).then(function(res){
               console.log(res.data);
            })

同源 和 跨域

同源

如果两个页面的协议、域名和端口都相同,则两个页面具有相同的源

%title插图%num

同源策略 (same origin policy)是浏览器提供的一个安全功能,该策略限制了从一个同源加载的文档或脚本如何与来自另一个源的资源进行交互,这是一个用于隔离潜在恶意文件的重要安全机制。

无法读取非同源网站的 Cookie、LocalStorage 和 indexedDB
无法接触非同源网页的DOM
无法向非同源地址发送Ajax请求

跨域

同源指的是两个URL的协议、域名、端口一致,反之则是跨域

%title插图%num

出现跨域问题后,虽然用户依旧可以发起请求和接收到跨域响应的数据,但是无法对页面获取到,因为浏览器将不允许 URL 之间进行资源交互,浏览器会对跨域请求进行拦截

解决跨域问题

实现跨域数据请求,最主要的两种解决方案为 JSONPCORS

JSONP 出现早,兼容好。但是它只是程序员被迫想出来的一种临时解决方案,只支持 GET 请求,不支持 POST 请求

CORS 出现比较晚,它是 W3C 标准,属于跨域请求的根本解决方案,支持 GET 和 POST 请求,缺点是不兼容某些低版本的浏览器。

JSONP

由于浏览器同源策略限制,网页中无法通过 Ajax 请求非同源的接口数据,但是 <script> 标签不受同源策略的影响,可以通过 src 属性,请求非同源的 js 脚本。

因此,JSONP 的实现原理,就是通过 <script> 标签的 src 属性,它不受跨域影响,因此使用它实现请求跨域的数据接口,并通过函数调用的形式,接收跨域接口响应回来的数据。JSONP 和 Ajax 之间没有任何关系,因为 JSONP 没有用到 XMLHttpRequest 对象

JSONP 是一种非官方跨域数据交互协议,是程序员彼此之间 给定的对接 暗号 的传递方式

客户端写法

    <script>
        // 打印数据 该方法用于 为服务器接收数据后的 回调函数
        function success(data){
            console.log(‘获取到了data数据’);
            console.log(data);
        }
    </script>
    <!– 请求的地址 并将数据返回到回调函数 success –>
    <script src=”https://smmcat.cn/study/jsonp.php?callback=success”></script>

jquery 实现 jsonp 请求:( {jsonp} 参数可修改发送到服务器的参数名称 {jsonpCallback} 参数修改回调函数名称 )

        // jQuery 发起 jsonp 请求
        $.ajax({
            url:’https://smmcat.cn/study/jsonp.php?callback’,
            // 如果要使用 $.ajax() 发起 jsonp 请求 必须指定 dataType 为 jsonp
            dataType:’jsonp’,
            success:function(res){
                console.log(res);
            }
        });

服务器端写法

<?php
header(‘Content-type: application/json’);
/ /获取回调函数名
$jsoncallback = htmlspecialchars($_REQUEST [‘jsoncallback’]);
// json数据
$json_data = ‘[“customername1″,”customername2”]’;
// 输出jsonp格式的数据
echo $jsoncallback . “(” . $json_data . “)”;
?>

节流 和 防抖

节流 n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖 n 秒 后再执行该事件,若在 n 秒内被重复触发,则重新计时

节流策略

%title插图%num

节流策略 (throttle) 可以减少一段时间内事件的触发频率

当用户执行 某项请求服务器 发送或接收 数据后,为了缓解服务器的频繁请求响应,我们一般会为函数 进行节流处理。(即 一段时间内只允许 请求 一次) 在节流期间的所有 用户请求 将不进行处理

        // 节流阀 初始化关闭
        let type = true;
        // 按钮被单击 执行绑定事件
        $(‘button’).click(function () {
            // 如果 节流阀为 关闭状态
            if (type) {
                // 将节流阀 打开
                type = false;
                // 发起 ajax 请求
                $.get(‘http://liulongbin.top:3006/api/getbooks’, function (res) {
                    // 打印结果
                    console.log(res);
                    // 开启定时器 3秒后将 节流阀 关闭
                    setTimeout(() => {
                        type = true;
                    }, 3000);
                });
            }

下方模型 单击后的1秒内 不执行任何操作

  • %title插图%num
  • %title插图%num

防抖策略

%title插图%num

防抖策略(debounce) 是当时间被触发后,延迟 n 秒后再 执行回调,如果在这 n 秒内事件又被触发,则 重新计时

可对用户的操作进行延时处理,当用户再次进行操作时,延时机制重置,

      // 定义一个 定时器 函数
      function debounceSearch(keyword) {
        // 设置用户输入结束后的 5毫秒 后执行 界面渲染 和 JSONP 请求
        timer = setTimeout(() => {
          // 发起JSOP请求
          getSuggestList(keyword);
        }, 500);
      }
      function xxx() {
        // 预清除定时器
        clearTimeout(timer);
        debounceSearch(keyword);
      }

下方模型单击后 3秒后改变宽度

HTTP 协议

互联网之间的通信协议

通信协议 (Communication Protocol) 是指通信双方完成通信所必须遵守的规则和约定。客户端与服务器实现网页内容传输,则通信的双方必须遵守网络内容的传输协议。

网页内容又叫做超文本,因此网页内容的传输协议又叫 超文本传输协议 (HyperText Transfer Protocol) 简称 HTTP协议

HTTP协议的交互模型

HTTP协议采用了 请求/响应 的交互模型

%title插图%num

HTTP请求消息

由于HTTP协议属属于客户端浏览器和服务器之间的通信协议,因此客户端发起的请求叫做HTTP请求,客户端发送到服务器的消息,叫做 HTTP请求消息。(HTTP请求消息 又叫做 HTTP请求报文)

%title插图%num

请求行

HTTP请求消息由 请求行(request line)、请求头部(header)、空行请求体 4个部分组成

%title插图%num

请求头部

%title插图%num

请求头部 用来 描述客户端的基本信息,从而把客户端相关的信息告知服务器,比如:User-Agent 用来说明当前是什么类型的浏览器,Content-Type 用来描述发送到服务器的数据格式,Accept 用来描述客户端能够接收什么类型的返回内容,Accept-Language 用来描述客户端期望接收哪种人类语言的文字内容

%title插图%num

空行

用于分割请求头部与请求体

请求体

请求体中存放的,是要通过 POST请求 方式 提交到服务器的数据,只有POST请求才有请求体,GET没有请求体

%title插图%num

HTTP响应消息

HTTP 响应消息由 状态行响应头部空行响应体 4个部分组成,响应消息 又称 响应报文

%title插图%num

状态行

%title插图%num

响应头

详细描述可以参考 官方文档

%title插图%num

空行

用于分隔 响应头部 与 响应体

响应体

响应体存放的,是服务器响应给客户端的资源内容

%title插图%num

HTTP请求方法

红色标注的为重点需要了解的方法

%title插图%num

HTTP响应状态码

HTTP响应状态码 (HTTP Status Code) ,也属于HTTP协议一部分,用来标识响应的状态,它会随着响应消息一起发送至客户端浏览器,浏览器根据服务器返回的响应状态码,就能知道 HTTP请求的结果是成功还是失败。

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字用来对状态码进行细分

分类 分类描述
1** 【信息】服务器收到请求,需要请求者继续执行操作(较少遇到)
2** 【成功】操作被成功接收并处理
3** 【重定向】需要进一步的操作以完成请求
4** 【客户端错误】请求包含语法错误或无法完成请求
5** 【服务器错误】服务器在处理请求的过程中发生了错误

2** 请求的常见响应状态码

%title插图%num

3** 请求的常见响应状态码

%title插图%num

4** 请求的常见响应状态码

%title插图%num

5** 请求的常见响应状态码

%title插图%num
Git 学习

手动命名版本号缺陷

操作麻烦 每次都需要复制粘贴
命名不规范 无法通过文件名知道具体做了哪些修改
容易丢失 如果硬盘故障或不小心删除,文件很容易丢失
协同困难 需要手动合并对个人对项目文件的修改,合并时极易出错

使用版本控制软件的好处

操作简便 只需要认识几组简单终端命令,即可快速上手常见版本控制软件
易于对比 基于版本控制软件提供的功能,能够方便的比较文件的变化细节,从而查找出导致问题的原因
易于回溯 可以将选定的文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态
不易丢失 在版本控制软件中,被用户误删除的文件,可以轻松的恢复回来
协作方便 基于版本控制软件提供的分支功能,可以轻松实现多人协作开发的代码合并操作

分布式版本管理系统

特点:基于服务器、客户端的运行模式。服务器保存文件的所有更新版本,客户端并同步保存完整备份。支持离线本地提交版本更新;

Git 介绍

%title插图%num

Git 是一个开源的分布式版本控制系统,是目前世界上最先进、最流行的版本控制系统。可以快速高效的处理从很小到非常大的项目版本管理

特点:记录快照,近乎所有的操作都是本地进行

Git 三个区域

使用 Git 管理的项目,拥有三个区域,分别是工作区暂存区Git仓库

工作区:程序员处理工作的区域 ↓
暂存区:已完成的工作的临时存放区域,等待被提交 ↓
Git仓库:最终存放版本的区域

Git 三个状态

%title插图%num

配置用户信息

前置环境安装

代码基于 Git Bash Here 客户端需要安装 Git 下载地址

安装完 Git 之后,要做的第一件事就是设置自己的用户名和邮箱地址,因为通过 GIT 对项目进行版本管理的时候,Git 需要使用这些基本信息,来记录是谁对项目进行了操作:(注意 global 是俩个 -)

# 设置用户名
git config --global user.name "youname"
# 设置用户邮箱
git config --global user.email "youemail"

如果使用了 --global 选项,那么该命令只需要运行一次,即可永久生效

通过 git config --global user.name "youname"git config --global user.email "youemail" 配置的用户名和邮箱地址,会被写入到 C:/Users/用户名文件夹/.gitconfig 文件中,这个文件是 Git 的 全局配置文件,配置一次即可永久生效

获取帮助信息

可以使用 git help <verb> 命令,无需联外即可在浏览器中打开帮助手册,例如:

# 打开 git config 命令的帮助手册
$ git help config

获取 Git仓库 的两种方法

本地目录 转换成 Git仓库

创建本地仓库

在项目目录中,通过鼠标右键打开 Git Bash , 执行 git init 命名可将当前目录转化为 Git仓库

# 初始化本地版本库
$ git init

效果如下

%title插图%num

Git init 命令会创建一个名为 .git 的隐藏目录,这个 .git 目录就是当前项目的 Git仓库,里面包含了初始的必要文件,这些文件是 Git仓库 的必要组成部分

检查文件状态

可以在 项目目录中 使用 git status 命令查看文件处于什么状态

# 查看状态
$ git status
# 查看状态 简化表示
$ git status -s

%title插图%num

上方为刚执行 git init 的文件夹,运行 git status 命名提示为 Untracked files (未跟踪的文件)

也可使用精简方式显示文件状态指令 git status -s 简化表示 (图中 ?? 为未跟踪文件

%title插图%num

未跟踪文件意味着在 Git在之前的快照 (提交) 中没有这些文件,Git 不会自动将之纳入跟踪范围,除非明确的告诉它 “我需要使用 Git 跟踪管理该文件”

Git 跟踪文件

使用 git add xxx 开始跟踪一个文件,会看到该文件在 Changes to be committed 这行的下面,说明已被跟踪,并处于暂存状态。( 新添加到暂存区中的文件会以 A 标记 )

若需要提交整个文件夹的内容 直接写 git add . 即可

# 提交文件 xxx
$ git add xxx
# 提交目录中所有文件
$ git add .
# 取消 暂存区的对应文件 xxx 提交
$ git resrt HEAD xxx
# 取消提交所有 暂存区的文件
$ git resrt HEAD .

效果如下

%title插图%num

Git 忽略跟踪文件

在文件目录中新建一个名为 .gitignore 文件,并用记事本打开,以 glob匹配模式的正则表达式 书写提交规则,git会自动过滤该文件下选中的文件。下方是参考例子

%title插图%num

Git 会忽略跟踪 .gitignore 里面选中的的文件,达到 过滤忽略文件 的提交效果

Git 提交更新

在暂存区有个 index.html 文件等待提交到 Git仓库 中进行保存,可以执行 git commit 命令进行提交,其中 -m 选项后面是本次提交消息,用来对提交的内容做进一步的描述

# 提交所有更新过的文件
$ git commit -m “更新介绍”

%title插图%num

跳过暂存 直接提交更新

该方式可无需前置操作 $ git add ,直接将 已跟踪的文件 (如 有改动过的文件提示为 M ) 提交到 Git仓库

# 直接提交目录中已跟踪文件
$ git commit -a -m “更新介绍”

效果如下

%title插图%num

回退 撤销对文件更改

【谨慎操作】该操作会对当前编辑的文件进行回退操作,把对工作区对应文件的修改,还原成 Git仓库 中所保存的版本

# 回退 index.html 版本 至 Git仓库 中所保存的版本
$ git checkout -- index.html
# 回退 目录中所有内容 至 Git仓库 中所保存的版本
$ git checkout -- .

移除 Git仓库 文件

从 Git仓库 中移除文件

# 从 Git仓库 和 工作区 中同时移除 index.js 文件
$ git rm -f index.js
# 只从 Git仓库 中移除 index.css 但保留工作区中的 index.css 文件
$ git rm --cached index.css

Git 查看提交历史

在使用 Git 提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,我们可以使用 git log 命令查看

# 查看日志 最新的提交排在最前面
$ git log
# 只展示最新的两条提交记录 数字可以按需要填写
$ git log -2
# 在一行上展示最近两条提交历史信息
$ git log -2 --pretty=oneline
#自定义输出的格式
$ git log -pretty=format:"%h |%an |%ar |%s"

%title插图%num

Git 回退到历史版本

回退版本的方式 可在查看日志中 取得 历史版本下的提交ID 进行回退

log:该命令可以显示所有提交过的版本信息
reflog:如果在回退以后又想再次回到之前的版本,git reflog 可以查看所有分支的所有操作记录

# 根据指定的提交ID 回退 或 还原 到指定版本
$ git reset --hard <commitID>
# 在旧版本中使用 git reflog 命令,查看命令操作的历史
$ git reflog --pretty=oneline

效果如下

%title插图%num

Git 分支操作

如若不 创建分支 的话,我们默认是在 Git的主分支 进行操作,这不利于团队开发。也不利于回退版本找到问题,因此我们需要对工程文件创建分支

分支操作 多用于专门分配开发目标,它是临时从 master主分支 上分叉出来的,当新功能开发且测试完毕后,最终需要合并到 master 主分支上

%title插图%num

# 查看分支
$ git branch
# 创建分支 xxx
$ git branch xxx
# 切换分支 xxx
$ git checkout xxx
# 创建并切换分支 xxx
$ git checkout -b xxx
# 将 xxx分支 合并到 主分支 (需要切换到 主分支上操作)
$ git merge xxx
# 删除已合并主分支的 xxx分支 (需要切换到 主分支上操作)
$ git branch -d xxx
# 强制删除 xxx分支 (即使它并没有合并到 主分支)
$ git branch -D xxx

效果如下

%title插图%num

分支冲突

当两个分支的项目中 都对一项文件进行了修改时,合并分支时候就会提示 分支冲突,因此就需要 用户 手动解决冲突

%title插图%num

用 vscode 打开,会提示冲突内容,需要手动解决该项目的冲突内容 (仅保存当前内容 或者 替换为分支内容等)

%title插图%num

再进行提交 即可提交成功 合并分支

%title插图%num

Git 常用代码

可直接查看 图片

创建版本库
$ git clone # 克隆远程版本库
$ git init # 初始化本地版本库
修改和提交
$ git status # 查看状态
$ git diff # 查看变更内容
$ git add . # 跟踪所有改动过的文件
$ git add <file> # 跟踪指定的文件
$ git mv <old> <new> # 文件改名
$ git rm <file> # 删除文件
$ git rm –cached <file> # 停止跟踪文件但不删除
$ git commit -m “commit message” # 提交所有更新过的文件
$ git commit –amend # 修改最后一次提交
查看提交历史
$ git log # 查看提交历史
$ git log -p <file> # 查看指定文件的提交历史
$ git blame <file> # 查看指定文件的提交历史
撤销
$ git reset –hard HEAD # 撤销工作的目录中所有未提交文件的修改内容
$ git checkout HEAD <file> # 撤销指定的未提交文件的修改内容
$ git revert <commit> # 撤销指定的提交
分支与标签
$ git branch # 显示所有本地分支
$ git checkout <branch/tag> # 切换到指定分支或标签
$ git branch <new-branch> # 创建新分支
$ git branch -d <branch> # 删除本地分支
$ git tag # 列出所有本地标签
$ git tag <tagname> # 基于最新提交创建标签
$ git tag -d <tagname> # 删除标签
合并和衔接
$ git merge <branch> # 合并指定分支到当前分支
$ git rebase <branch> # 衍和指定分支到当前分支
远程操作
$ git remove -v # 查看远程版本库信息
$ git remove show <remote> # 查看指定远程版本库信息
$ git remove add <remote> <url> # 添加远程版本库
$ git fetch <remote> # 从远程库中获取代码
$ git pull <remote> <branch> # 下载代码及快速合并
$ git push <remote> <branch> # 上传代码及快速合并
$ git push <remote> :<branch/tag-name> # 删除远程分支或标签
$ git push –tags # 上传所有标签

GitHub的使用

%title插图%num

GitHub 使用SSH 绑定本地 Git

打开 GitBash 使用如下代码,输入后连续敲击三次回车,即可在 C:\Users\用户名文件夹\.ssh 目录中生成 id_rsaid_rsa.pub 两个文件

$ ssh-keygen -t rsa -b 4096 -C “youGitHub@email.com”

效果如下

%title插图%num

找到 id_rsa.pub 该文件,用记事本打开该文件,复制该文件内容。粘贴到你上个操作中对应输入的邮箱的 GitHub 账号,在设置>SSH 和 GPG密匙 中的 SSH密匙 选项,粘贴SSH密匙

%title插图%num

验证绑定,输入以下代码

$ ssh -T git@github.com

效果如下

%title插图%num

当提示 …Are you sure you want to continue connecting (yes/no/[fingerprint])? 后,输入yes,提示你的账号名,则绑定成功

Git仓库 使用 HTTP 的方式上传到 GitHub仓库

1.新建仓库

在 GitHub 上进行操作 (实际上 GitHub上会有教程提示 如何 http 上传 与 ssh 上传)

%title插图%num

2.指令上传

# 将本地仓库和远程仓库进行关联 并把远程仓库命名为 xx
git remote add xx https://github.com/xx…
# 将本地仓库中的内容 推送到 远程的 xx 仓库中
git push -u xx master

效果如下

%title插图%num

更新 Github仓库的内容

第一次推送,必须运行 上方的完整的命令,但是后续更新仓库内容时,仅需要运行以下命令即可同步

# 更新GitHub仓库的内容 为 本地目录 Git仓库内容
$ git push

效果如下

%title插图%num

克隆GitHub仓库 到本地

一般用户误删除目录时,可直接使用以下代码 获取到以前 GitHub仓库 备份的代码项目

远程仓库地址获取方式

%title插图%num

# 克隆远程仓库
$ git clone 远程仓库地址

效果如下

%title插图%num

将 本地分支 推送到 GitHub仓库

将本地 Git仓库 绑定到 Github仓库 后,首次推送分支时候需要携带 -u 参数

# -u 表示把本地分支和远程分支进行关联 仅再第一次推送时需要携带
$ git push -u 远程仓库别名(默认为 origin) 分支名:分支别名
# 如果希望远程分支名称与本地分支保持一致 可对命令简化
$ git push -u 远程仓库别名(默认为 origin) 分支名

效果如下

%title插图%num

查看远程仓库所有分支列表

通过如下命令,可以查看远程仓库中,所有分支列表的信息

$ git remote show 远程仓库名(默认为 origin)

效果如下

%title插图%num

跟踪远程分支

若删除了本地分支,可以进行跟踪分支还原,跟踪分支指的是将远程分支下载到本地仓库中。(适用于再次关联本地与远程分支 并搭配 $ git pull 指令)

# 从远程仓库中 把对应的远程分支下载到本地仓库,保持本地分支和远程分支名称相同
$ git checkout 远程分支名称
# 从远程仓库中 把对应的远程分支下载到本地仓库,并本地重命名该分支
$ git checkout -b 本地分支名称 远程仓库名称(默认为 origin)/远程分支名称

效果如下

%title插图%num

拉取远程分支

当 远程仓库的 分支版本 发生了改动,为了获取 该远程分支 下的最新代码,可以使用 拉取远程分支

# 从远程仓库拉去取当前分支的最新代码,保持当前分支的代码和远程分支代码一致
$ git pull

效果如下

%title插图%num

删除远程分支

可以使用如下的命令,删除远程仓库中指定的分支

# 删除远程仓库中 指定名称的远程分支
$ git push 远程仓库名称(默认为 origin) –delete 远程分支名称

效果如下

%title插图%num