ajax及模板引擎、XMLHttpRequest2、axios

Ajax

自学地址–>B站黑马程序员


基础

URL地址

统一资源定位符,网页资源统一标识符。

在这里插入图片描述

客户端和服务器通信过程

在这里插入图片描述

浏览器开发工具分析通信过程

在这里插入图片描述

HTML是网页的骨架
CSS是网页的颜值
Javascript是网页的行为

数据,则是网页的灵魂

在这里插入图片描述

在这里插入图片描述

客户端请求服务器时,请求的方式有很多种,最常见的两种请求方式分别为 get 和 post 请求。
get 请求通常用于获取服务端资源(向服务器要资源)
例如:根据 URL 地址,从服务器获取 HTML 文件、css 文件、js文件、图片文件、数据资源等

post 请求通常用于向服务器提交数据(往服务器发送资源)
例如:登录时向服务器提交的登录信息、注册时向服务器提交的注册信息、添加用户时向服务器提交的用户信息等各种数据提交操作

接口

请求数据时,被请求的 URL 地址,就叫做数据接口(简称接口)。

同时,每个接口必须有请求方式。具体需要哪些操作可查看接口文档。

接口测试工具:(好处:不用写代码)

在这里插入图片描述

PostMan下载地址:https://www.postman.com/downloads/

或中文版工具apifox:https://www.apifox.cn/

中文版工具apifox帮助地址:帮助中心 | Apifox 使用文档

在这里插入图片描述

初识Ajax

全称是 Asynchronous Javascript And XML(异步 JavaScript 和 XML)。
通俗的理解:在网页中利用 XMLHttpRequest 对象和服务器进行数据交互的方式,就是Ajax。

Ajax能让我们轻松实现网页与服务器之间的数据交互。

应用场景:

  • 注册用户时动态检测用户名是否被占用
  • 搜索提示列表
  • 数据分页显示
  • 数据的增删改查

jQuery中的Ajax

由于浏览器中提供的 XMLHttpRequest 用法比较复杂。

所以 jQuery 对 XMLHttpRequest 进行了封装,提供了一系列 Ajax 相关的函数,极大地降低了 Ajax 的使用难度。

jQuery 中发起 Ajax 请求最常用的三个方法如下:

  1. $.get()
  2. $.post()
  3. $.ajax()

1、$.get()

功能单一,发起 get 请求,从服务器拿数据。

$.get(url, [data], [callback])
//参数一:url	string类型	要请求的资源地址
//参数二:data	object类型	请求资源期间要携带的参数
//参数三:callback	请求成功时的回调函数

2、$.post()

功能单一,发起 post 请求,向服务器提交数据。

$.post(url, [data], [callback]);
//参数一:url	string类型	提交数据的地址
//参数二:data	object类型	要提交的数据
//参数三:callback	数据提交成功时的回调函数

3、$.ajax()

功能更多

$.ajax({
   type: '', // 请求的方式 GET 或 POST
   url: '',  // 请求的URL
   data: { },// 请求要携带的数据
   success: function(res) { } // 请求成功之后的回调函数
})

添加删除图书:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel="stylesheet" href="./lib/bootstrap.css" />
  <script src="./lib/jquery.js"></script>
</head>

<body style="padding: 20px;">

  <!-- 添加图书的Panel面板 bs3 -->
  <div class="panel panel-primary">
    <div class="panel-heading">
      <h3 class="panel-title">添加新图书</h3>
    </div>
    <div class="panel-body form-inline">

      <div class="input-group">
        <div class="input-group-addon">书名</div>
        <input type="text" class="form-control" id="iptBookname" placeholder="请输入书名">
      </div>

      <div class="input-group">
        <div class="input-group-addon">作者</div>
        <input type="text" class="form-control" id="iptAuthor" placeholder="请输入作者">
      </div>

      <div class="input-group">
        <div class="input-group-addon">出版社</div>
        <input type="text" class="form-control" id="iptPublisher" placeholder="请输入出版社">
      </div>

      <button id="btnAdd" class="btn btn-primary">添加</button>

    </div>
  </div>


  <!-- 图书的表格 -->
  <table class="table table-bordered table-hover">
    <thead>
      <tr>
        <th>Id</th>
        <th>书名</th>
        <th>作者</th>
        <th>出版社</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody id="tb"></tbody>
  </table>

  <script>
    $(function () {
      /* 从接口获取数据 */
      function getBooks() {
        $.get('http://www.liulongbin.top:3006/api/getbooks', function (res) {
          console.log(res);
          if (res.status !== 200) return alert('false')
          var items = new Array();
          $.each(res.data, function (i, ele) {
            console.log(i+"->"+ele.id + "-" + ele.bookname + "-" + ele.author + "-" + ele.publisher);
            items.push('<tr><td>' + ele.id + '</td><td>' + ele.bookname + '</td><td>' + ele.author + '</td><td>' + ele.publisher + '</td><td><a href="javascript:;" class="del" data-id="' + ele.id + '">删除</a></td></tr>')
          })
          $('#tb').empty().append(items.join(''))
        })
      }
      getBooks()
      // $('.del').on('click', function () {
      //   console.log('hello del');
      // })
      /* 动态创建元素,需要事件委派绑定事件 */
      $('#tb').on('click', '.del', function () {
        console.log('del')
        var id = $(this).data('id')
        console.log(id);
        /* 根据id删除一条数据 */
        $.get('http://www.liulongbin.top:3006/api/delbook', { id: id }, function (res) {
          if (res.status !== 200) return alert('false')
          getBooks()
        })
      })

      /* 新增数据 */
      $('#btnAdd').on('click', function () {

        var iptBookname = $('#iptBookname').val().trim()
        var iptAuthor = $('#iptAuthor').val().trim()
        var iptPublisher = $('#iptPublisher').val().trim()
        if (iptBookname.length <= 0 || iptAuthor.length <= 0 || iptPublisher.length <= 0) return alert('不能为空!')
        var newBook = {
          bookname: iptBookname,
          author: iptAuthor,
          publisher: iptPublisher
        }
        $.post('http://www.liulongbin.top:3006/api/addbook', newBook, function (res) {
          if (res.status !== 201) return alert('false')
          getBooks()
          $('#iptBookname').val('')
          $('#iptAuthor').val('')
          $('#iptPublisher').val('')
        })
      })
    })
  </script>
 
</body>

</html>

form表单与模板引擎

form表单

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

表单由三个基本部分组成:

在这里插入图片描述

🟥:form表单标签

🟩:表单域。包含了文本框、密码框、隐藏域、多行文本框、复选框、单选框、下拉选择框和文件上传框等。

🟦:表单按钮

form标签的属性:

1、action:

提交表单时,向何处发送表单数据。
值是 URL 地址,这个 URL 专门负责接收表单提交过来的数据。
form 表单在未指定 action 属性值的情况下,action 的默认值为当前页面的 URL 地址。

提交表单后,页面会跳转到 action 属性指定的 URL 地址

2、target:

在何处打开action URL。

默认情况下,target 的值是 _self,表示在相同的框架中打开 action URL。

描述
_blank在新窗口中打开。
_self在相同的窗口中打开。(默认)
_parent在父框架集中打开。(很少用)
_top在整个窗口中打开。(很少用)
framename在指定的框架中打开。(很少用)

3、method:

method 属性规定以何种方式把表单数据提交到 action URL。
可选值有两个: get(默认) 和 post。

🔸注意:
get 方式适合用来提交少量的、简单的数据。
post 方式适合用来提交大量的、复杂的、或包含文件上传的数据。
实际开发中,form 表单的 post 提交方式用的最多,很少用 get。例如登录、注册、添加数据等表单操作,都需要使用 post 方式来提交表单。

4、enctype

规定在发送表单数据之前如何对数据进行编码。

可选值有三个,默认情况下enctype 的值为 application/x-www-form-urlencoded,表示在发送前编码所有的字符。

描述
application/x-www-form-urlencoded在发送前编码所有字符(默认)
multipart/form-data不对字符编码。 在使用包含文件上传控件的表单时,必须使用该值。
text/plain空格转换为 “+” 加号,但不对特殊字符编码。(很少用)

🔸注意:
在涉及到文件上传的操作时,必须将 enctype 的值设置为 multipart/form-data
如果表单的提交不涉及到文件上传操作,不用加此属性就行。


表单的同步提交

通过点击 submit 按钮,触发表单提交的操作,从而使页面跳转到 action URL 的行为,叫做表单的同步提交。

缺点:

1.表单同步提交后,整个页面会发生跳转,跳转到 action URL 所指向的地址,用户体验差。
2.表单同步提交后,页面之前的状态和数据会丢失

解决:

表单只负责采集数据,Ajax 负责将数据提交到服务器。


Ajax提交表单数据

监听表单提交事件:

//方法一:
$('#form1').submit(function(e) {
   alert('监听到了表单的提交事件')
})
//方法二:
$('#form1').on('submit', function(e) {
   alert('监听到了表单的提交事件')
})

阻止表单默认提交行为:event.preventDefault()

$('#form1').submit(function(e) {
   // 阻止表单提交和页面跳转
   e.preventDefault()
})

$('#form1').on('submit', function(e) {
   // 阻止表单提交和页面跳转
   e.preventDefault()
})

获取表单数据:

jQuery 提供的 serialize() 函数,可以一次性获取表单中所有数据。使用 **serialize() **时,必须每个表单元素添加 name 属性。

例如:表单如下

<form id="form1">
    <input type="text" name="name" />
    <input type="password" name="password" />
    <button type="submit">提交</button>
</form>

serialize() 函数获取数据:

$('#form1').serialize()
// 数据:
// name=值&password=值

模板引擎

渲染UI结构时遇到的问题,需要拼接的元素太长,结构比较复杂:

li.push('<li class="list-group-item">'+ item.content +'<span class="badge cmt-date">评论时间:'+ item.time +'</span><span class="badge cmt-person">评论人:'+ item.username +'</span></li>')

模板引擎,就是程序员指定的模板结构和数据。

定义HTML页面,然后js提供数据。

art-template模板引擎

网址: http://aui.github.io/art-template/zh-cn/index.html

下载js文件:http://aui.github.io/art-template/zh-cn/docs/installation.html

在这里插入图片描述

使用模板引擎步骤:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>模板引擎</title>
  <!-- 1. 导入模板引擎template-web.js文件 -->
  <script src="./lib/template-web.js"></script>
  <script src="./lib/jquery.js"></script>
</head>

<body>

  <div id="container"></div>

  <!-- 2. 定义模板,在script中定义的HTML需要指定html解析type="text/html" -->
  <script type="text/html" id="example">
  	<!-- {{}}表示占位符,是要传入的数据 -->
    <h1>{{name}}</h1>
  </script>

  <script>
    // 3. 取出数据
    var data = { name: 'roydon' }
    // 4. 调用模板引擎提供的 template 函数(第一个参数表示模板的id,第二个参数是数据)
    var temp = template('example', data)
    // 5. 渲染HTML
    $('#container').html(temp)
  </script>
  
</body>

</html>

art-template标准语法

art-template 提供了 {{ }} 这种语法格式,在 {{ }} 内可以进行变量输出,或循环数组等操作,这种 {{ }} 语法在 art-template 中被称为标准语法。

{{value}}
{{obj.key}}//对象属性的输出
{{obj['key']}}//对象属性的输出
{{a ? b : c}}//三元表达式
{{a || b}}//逻辑
{{a + b}}//运算
//若数据值包含HTML结构需要完整输出且被渲染,则:
{{@ value }}

条件输出:

{{if condition}} 按需输出的内容 {{/if}}
{{if condition1}} 按需输出的内容 {{else if condition2}} 按需输出的内容 {{/if}}

在这里插入图片描述

循环输出:

{{each arr}}
    {{$index}} {{$value}}
{{/each}}

例如输出数组:{ arr: [‘1’, ‘2’, ‘3’] }

<ul>
  {{each arr}}
  <li>索引:{{$index}}:{{$value}}</li>
  {{/each}}
</ul>

过滤器

{{value | filterName}}
//定义过滤器,过滤器名称filterName
template.defaults.imports.filterName = function(value){
    /*return处理的结果*/
}

实现原理:

正则与字符串操作

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

例如:

var str = 'hello'
var pattern = /o/                         
// 输出的结果["o", index: 4, input: "hello", groups: undefined]
console.log(pattern.exec(str)) 

正则表达式中 ( ) 包起来的内容表示一个分组,可以通过分组来提取自己想要的内容,示例代码如下:

 var str = '<div>我是{{name}}</div>'
 var pattern = /{{([a-zA-Z]+)}}/

 var patternResult = pattern.exec(str)
 console.log(patternResult)
 // 得到 name 相关的分组信息
 // ["{{name}}", "name", index: 7, input: "<div>我是{{name}}</div>", groups: undefined]

字符串的replace()函数用于在字符串中用一些字符替换另一些字符,语法格式如下:

var result = '123456'.replace('123', 'abc') // 得到的 result 的值为字符串 'abc456'

用while循环替换:

var str = '<div>{{name}}今年{{ age }}岁了</div>'
var pattern = /{{\s*([a-zA-Z]+)\s*}}/
var patternResult = null
while(patternResult = pattern.exec(str)) {
   str = str.replace(patternResult[0], patternResult[1])
}
console.log(str) // 输出 <div>name今年age岁了</div>

替换为数据中的值:

var data = { name: '张三', age: 20 }
var str = '<div>{{name}}今年{{ age }}岁了</div>'
var pattern = /{{\s*([a-zA-Z]+)\s*}}/

var patternResult = null
while ((patternResult = pattern.exec(str))) {
   str = str.replace(patternResult[0], data[patternResult[1]])
}
console.log(str)

自定义模板引擎,封装template函数:

function template(id, data) {
  var str = document.getElementById(id).innerHTML
  var pattern = /{{\s*([a-zA-Z]+)\s*}}/
  var pattResult = null
  while (pattResult = pattern.exec(str)) {
    str = str.replace(pattResult[0], data[pattResult[1]])
  }
  return str
}

Ajax加强

XMLHttpRequest

XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,通过它,可以请求服务器上的数据资源。之前所学的 jQuery 中的 Ajax 函数,就是基于 xhr 对象封装出来的。

在这里插入图片描述

使用xhr发起GET请求
// 1. 创建 XHR 对象
var 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 () {
    //监听 xhr 对象的请求状态 readyState ;与服务器响应的状态 status
  if (xhr.readyState === 4 && xhr.status === 200) {
    // 获取服务器响应的数据
    console.log(xhr.responseText)
  }
}

readyState属性:表示当前 Ajax 请求所处的状态,每个 Ajax 请求必然处于以下状态中的一个:

状态描述
0UNSENTXMLHttpRequest 对象已被创建,但尚未调用 open方法。
1OPENEDopen() 方法已经被调用。
2HEADERS_RECEIVEDsend() 方法已经被调用,响应头也已经被接收。
3LOADING数据接收中,此时 response 属性中已经包含部分数据。
4DONEAjax 请求完成,这意味着数据传输已经彻底完成或失败。

使用 xhr 对象发起带参数的 GET 请求时,只需在调用 xhr.open 期间,为 URL 地址指定参数即可:

这种在 URL 地址后面拼接的参数,叫做·查询字符串·。

在这里插入图片描述

什么是查询字符串?

定义:查询字符串(URL 参数)是指在 URL 的末尾加上用于向服务器发送信息的字符串(变量)。
格式:将英文的?放在URL 的末尾,然后再加上 参数=值 ,想加上多个参数的话,使用 & 符号进行分隔。以这个形式,可以将想要发送给服务器的数据添加到 URL 中。

// 不带参数的 URL 地址
http://www.liulongbin.top:3006/api/getbooks
// 带一个参数的 URL 地址
http://www.liulongbin.top:3006/api/getbooks?id=1
// 带两个参数的 URL 地址
http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记

GET请求携带参数的本质:

无论使用 $.ajax(),还是使用 $.get(),又或者直接使用 xhr 对象发起 GET 请求,当需要携带参数的时候,本质上,都是直接将参数以查询字符串的形式,追加到 URL 地址的后面,发送到服务器的。

$.get('url', {name: 'zs', age: 20}, function() {})
// 等价于
$.get('url?name=zs&age=20', function() {})

$.ajax({ method: 'GET', url: 'url', data: {name: 'zs', age: 20}, success: function() {} })
// 等价于
$.ajax({ method: 'GET', url: 'url?name=zs&age=20', success: function() {} })

什么是URL编码?

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

浏览器提供了 URL 编码与解码的 API,分别是:

  • encodeURI() 编码的函数

  • decodeURI() 解码的函数

URL编码的原则:使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。
URL编码原则的通俗理解:使用英文字符去表示非英文字符。

在这里插入图片描述


使用xhr发起POST请求
// 1. 创建 xhr 对象
var 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 () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseText)
  }
}

数据交换格式

数据交换格式,就是服务器端与客户端之间进行数据传输与交换的格式。
前端领域,经常提及的两种数据交换格式分别是 XML 和 JSON。其中 XML 用的非常少,所以,重点要学习的数据交换格式就是 JSON。

XML 的英文全称是 EXtensible Markup Language,即可扩展标记语言。因此,XML 和 HTML 类似,也是一种标记语言。虽然都是标记语言,但是,它们两者之间没有任何的关系。

  • HTML 被设计用来描述网页上的内容,是网页内容的载体
  • XML 被设计用来传输和存储数据,是数据的载体

JSON 的英文全称是 JavaScript Object Notation,即“JavaScript 对象表示法”。简单来讲,JSON 就是 Javascript 对象和数组的字符串表示法,它使用文本表示一个 JS 对象或数组的信息,因此,JSON 的本质是字符串。
作用:JSON 是一种轻量级的文本数据交换格式,在作用上类似于 XML,专门用于存储和传输数据,但是 JSON 比 XML 更小、更快、更易解析。
现状:JSON 是在 2001 年开始被推广和使用的数据格式,到现今为止,JSON 已经成为了主流的数据交换格式。

JSON 就是用字符串来表示 Javascript 的对象和数组。所以,JSON 中包含对象和数组两种结构,通过这两种结构的相互嵌套,可以表示各种复杂的数据结构。

JSON的两种结构

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

{
    name: "zs",
    'age': 20,
    "gender": '男',
    "address": undefined,
    "hobby": ["吃饭", "睡觉", '打豆豆']
    say: function() {}
}

数组结构:数组结构在 JSON 中表示为 [ ] 括起来的内容。数据结构为 [ “java”, “javascript”, 30, true … ] 。数组中数据的类型可以是数字、字符串、布尔值、null、数组、对象6种类型。

[ "java", "python", "php" ]
[ 100, 200, 300.5 ]
[ true, false, null ]
[ { "name": "zs", "age": 20}, { "name": "ls", "age": 30} ]
[ [ "苹果", "榴莲", "椰子" ], [ 4, 50, 5 ] ]

JSON语法注意事项

  • 属性名必须使用双引号包裹
  • 字符串类型的值必须使用双引号包裹
  • JSON 中不允许使用单引号表示字符串
  • SON 中不能写注释
  • JSON 的最外层必须是对象或数组格式
  • 不能使用 undefined 或函数作为 JSON 的值
    JSON 的作用:在计算机与网络之间存储和传输数据。
    JSON 的本质:用字符串来表示 Javascript 对象数据或数组数据

JSON和JS对象的关系:

JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。例如:

//这是一个对象
var obj = {a: 'Hello', b: 'World'}

//这是一个 JSON 字符串,本质是一个字符串
var json = '{"a": "Hello", "b": "World"}' 

JSON和JS对象的互转:

  1. JSON 字符串转换为 JS 对象,使用 JSON.parse() 方法:
var obj = JSON.parse('{"a": "Hello", "b": "World"}')
//结果是 {a: 'Hello', b: 'World'}
  1. JS 对象转换为 JSON 字符串,使用 JSON.stringify() 方法:
var json = JSON.stringify({a: 'Hello', b: 'World'})
//结果是 '{"a": "Hello", "b": "World"}'

序列化和反序列化

把数据对象转换为字符串的过程,叫做序列化,例如:调用 JSON.stringify() 函数的操作,叫做 JSON 序列化。
把字符串转换为数据对象的过程,叫做反序列化,例如:调用 JSON.parse() 函数的操作,叫做 JSON 反序列化。


封装自己的Ajax函数

略~


XMLHttpRequest Level2的新特性

旧版XMLHttpRequest的缺点:

  • 只支持文本数据的传输,无法用来读取和上传文件
  • 传送和接收数据时,没有进度信息,只能提示有没有完成

XMLHttpRequest Level2的新功能

  • 可以设置 HTTP 请求的时限
  • 可以使用 FormData 对象管理表单数据
  • 可以上传文件
  • 可以获得数据传输的进度信息

设置HTTP请求时限

有时,Ajax 操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。新版本的 XMLHttpRequest 对象,增加了 timeout 属性,可以设置 HTTP 请求的时限:

 xhr.timeout = 3000

最长等待时间设为 3000 毫秒。过了这个时限,就自动停止HTTP请求。与之配套的还有一个 timeout 事件,用来指定回调函数:

 xhr.ontimeout = function(event){
     alert('请求超时!')
 }

FormData对象管理表单数据

Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作:

// 1. 创建 FormData 实例
var fd = new FormData()
// 2. 调用 append 函数,向 FormData 中追加数据
fd.append('uname', 'zs')
fd.append('upwd', '123456')
// 3. 创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest()
// 4. 指定请求类型与URL地址
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
// 5. 直接提交 FormData 对象,这与提交网页表单的效果,完全一样
xhr.send(fd)

xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(JSON.parse(xhr.responseText))
  }
}

FormData对象也可以用来获取网页表单的值,示例代码如下:

// DOM 操作,获取到 form 表单元素
var form = document.querySelector('#form1')
form.addEventListener('submit', function (e) {
  e.preventDefault()
  // 根据 form 表单创建 FormData 对象,会自动将表单数据填充到 FormData 对象中
  var fd = new FormData(form)
  var xhr = new XMLHttpRequest()
  xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
  xhr.send(fd)

  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
      console.log(JSON.parse(xhr.responseText))
    }
  }
})

上传文件

<!-- 1. 文件选择框 -->
<input type="file" id="file1" />
<!-- 2. 上传文件的按钮 -->
<button id="btnUpload">上传文件</button>
<br />
<!-- 3. img 标签,来显示上传成功以后的图片 -->
<img src="" alt="" id="img" width="800" />
// 1. 获取到文件上传按钮
var btnUpload = document.querySelector('#btnUpload')
// 2. 为按钮绑定单击事件处理函数
btnUpload.addEventListener('click', function () {
  // 3. 获取到用户选择的文件列表
  var files = document.querySelector('#file1').files
  if (files.length <= 0) return alert('请选择要上传的文件!')
  var fd = new FormData()
  // 将用户选择的文件,添加到 FormData 中
  fd.append('avatar', files[0])
  var xhr = new XMLHttpRequest()
  xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
  xhr.send(fd)

  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
      var data = JSON.parse(xhr.responseText)
      console.log(data);
      if (data.status === 200) {
        // 上传成功
        document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
      } else {
        // 上传失败
        console.log('图片上传失败!' + data.message)
      }
    }
  }
})

显示文件上传进度

新版本的 XMLHttpRequest 对象中,可以通过监听 xhr.upload.onprogress 事件,来获取到文件的上传进度。语法格式如下:

<!-- bootstrap 中的进度条 -->
<div class="progress" style="width: 500px; margin: 15px 10px;">
  <div class="progress-bar progress-bar-striped active" style="width: 0%" id="percent">
    0%
  </div>
</div>

// 将用户选择的文件,添加到 FormData 中
fd.append('avatar', files[0])
var xhr = new XMLHttpRequest()
// 监听文件上传的进度
xhr.upload.onprogress = function (e) {
  if (e.lengthComputable) {
    // 计算出上传的进度
    var procentComplete = Math.ceil((e.loaded / e.total) * 100)
    console.log(procentComplete)
    // 动态设置进度条
    $('#percent').attr('style', 'width: ' + procentComplete + '%;').html(procentComplete + '%')
  }
}

xhr.upload.onload = function () {
  $('#percent').removeClass().addClass('progress-bar progress-bar-success')
}

jQuery实现文件上传

<input type="file" id="file1" />
<button id="btnUpload">上传文件</button>
<br />
<img src="./images/loading.gif" alt="" style="display: none;" id="loading" />
$(function () {
  // 监听到Ajax请求被发起了$(document).ajaxStart() 函数会监听当前文档内所有的 Ajax 请求。
  $(document).ajaxStart(function () {
    $('#loading').show()
  })

  // 监听到 Ajax 完成的事件
  $(document).ajaxStop(function () {
    $('#loading').hide()
  })

  $('#btnUpload').on('click', function () {
    //1. 将 jQuery 对象转化为 DOM 对象,并获取选中的文件列表
    var files = $('#file1')[0].files
    if (files.length <= 0) {
      return alert('请选择文件后再上传!')
    }
	// 向 FormData 中追加文件
    var fd = new FormData()
    fd.append('avatar', files[0])

    // 发起 jQuery 的 Ajax 请求,上传文件
    $.ajax({
      method: 'POST',
      url: 'http://www.liulongbin.top:3006/api/upload/avatar',
      data: fd,
      // 不修改 Content-Type 属性,使用 FormData 默认的 Content-Type 值
      contentType: false,
      // 不对 FormData 中的数据进行 url 编码,而是将 FormData 数据原样发送到服务器
      processData: false,
      success: function (res) {
        console.log(res)
      }
    })
  })
})

axios

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

axios发起GET请求

document.querySelector('#btn1').addEventListener('click', function () {
  var url = 'http://www.liulongbin.top:3006/api/get'
  // 请求的参数对象
  var paramsObj = { name: 'zs', age: 20 }
  axios.get(url, { params: paramsObj }).then(function (res) {
    console.log(res.data)
  })
})

axios发起POST请求

document.querySelector('#btn2').addEventListener('click', function () {
  var url = 'http://www.liulongbin.top:3006/api/post'
  // 要提交到服务器的数据
  var dataObj = { address: '北京', location: '顺义区' }
  axios.post(url, dataObj).then(function (res) {
    // res.data 是服务器返回的数据
    console.log(res.data)
  })
})

直接使用axios发起请求

axios 也提供了类似于 jQuery 中 $.ajax() 的函数,语法如下:

axios({
    method: '请求类型',
    url: '请求的URL地址',
    data: {/*POST数据*/},
    params: {/*GET参数*/}
}).then(callback)
  1. 直接使用axios发起GET请求:
document.querySelector('#btn3').addEventListener('click', function () {
  var url = 'http://www.liulongbin.top:3006/api/get'
  var paramsData = { name: '钢铁侠', age: 35 }
  axios({
    method: 'GET',
    url: url,
    params: paramsData
  }).then(function (res) {
    console.log(res.data)
  })
})
  1. 直接使用axios发起POST请求:
document.querySelector('#btn4').addEventListener('click', function () {
  axios({
    method: 'POST',
    url: 'http://www.liulongbin.top:3006/api/post',
    data: {
      name: 'abc',
      age: 18,
      gender: '女'
    }
  }).then(function (res) {
    console.log(res.data)
  })
})

跨域与JSONP

同源策略

同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能。

如果两个页面的协议,域名和端口都相同,则两个页面具有相同的源。
例如,下表给出了相对于 http://www.test.com/index.html 页面的同源检测:

未指定端口的,端口默认为80.

URL是否同源原因
http://www.test.com/other.html同源(协议、域名、端口相同)
https://www.test.com/about.html协议不同(http 与 https)
http://blog.test.com/movie.html域名不同(www.test.com 与 blog.test.com)
http://www.test.com:7001/home.html端口不同(默认的 80 端口与 7001 端口)
http://www.test.com:80/main.html同源(协议、域名、端口相同)

MDN 官方给定的概念:同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

通俗的理解:浏览器规定,A 网站的 JavaScript,不允许和非同源的网站 C 之间,进行资源的交互,例如:

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

跨域

同源指的是两个 URL 的协议、域名、端口一致,反之,则是跨域。
出现跨域的根本原因:浏览器的同源策略不允许非同源的 URL 之间进行资源的交互。
网页:http://www.test.com/index.html
接口:http://www.api.com/userlist

在这里插入图片描述

注意:浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器拦截,无法被页面获取到!

实现跨域数据请求:

两种解决方案: JSONP 和 CORS。
JSONP:出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。
CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。


JSONP

JSONP (JSON with Padding) 是 JSON 的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。

由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。但是

实现:

<script>
    function abc(data) {
      console.log('JSONP响应回来的数据是:')
      console.log(data)
    }
</script>

<script src="http://ajax.frontend.itheima.net:3006/api/jsonp?callback=abc&name=ls&age=30"></script>

由于 JSONP 是通过

注意:JSONP 和 Ajax 之间没有任何关系,不能把 JSONP 请求数据的方式叫做 Ajax,因为 JSONP 没有用到 XMLHttpRequest 这个对象。

jQuery中的JSONP

jQuery 提供的 $.ajax() 函数,除了可以发起真正的 Ajax 数据请求之外,还能够发起 JSONP 数据请求,例如:

$.ajax({
  url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
  // 代表我们要发起JSONP的数据请求
  // 如果要使用 $.ajax() 发起 JSONP 请求,必须指定 datatype 为 jsonp
  dataType: 'jsonp',
  // 发送到服务端的参数名称,默认值为 callback
  jsonp: 'callback',
  // 自定义的回调函数名称,默认值为 jQueryxxx 格式
  jsonpCallback: 'abc',
  success: function (res) {
    console.log(res)
  }
})

jQuery 中的 JSONP,也是通过

  • 在发起 JSONP 请求的时候,动态向
    中 append 一个

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

在这里插入图片描述

防抖的应用场景:

  • 用户在输入框中连续输入一串字符时,可以通过防抖策略,只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源。

实现输入框的防抖:

 var timer = null                    //1. 防抖动的timer
 function debounceSearch(keywords) { //2. 定义防抖的函数
    timer=setTimeout(function(){
    //发起JSONP请求
    getSuggestList(keywords)
    },500)
 }
 $('#ipt').on('keyup', function() {  //3. 在触发 keyup 事件时,立即清空 timer
	clearTimeout(timer)
    // ...省略其他代码
    debounceSearch(keywords)
 })

节流:

节流策略(throttle),顾名思义,可以减少一段时间内事件的触发频率。

在这里插入图片描述

节流的应用场景:

  • 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;
  • 懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源;

使用节流优化鼠标跟随效果:

// 1. 获取到图片
var angel = $('#angel')
// 步骤1. 定义节流阀
var timer = null
// 2. 绑定 mousemove 事件
$(document).on('mousemove', function (e) {
  // 3:判断节流阀是否为空,如果不为空,则证明距离上次执行间隔不足16毫秒
  if (timer) { return }
  // 4:开启延时器
  timer = setTimeout(function () {
    $(angel).css('top', e.pageY + 'px').css('left', e.pageX + 'px')
    // 5.当设置了鼠标跟随效果后,清空 timer 节流阀,方便下次开启延时器
    timer = null
  }, 16)
})

HTTP 协议即超文本传送协议 (HyperText Transfer Protocol) ,它规定了客户端与服务器之间进行网页内容传输时,所必须遵守的传输格式。
例如:
客户端要以HTTP协议要求的格式把数据提交到服务器
服务器要以HTTP协议要求的格式把内容响应给客户端

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

客户端发起的请求叫做 HTTP 请求,客户端发送到服务器的消息,叫做 HTTP 请求消息。HTTP 请求消息又叫做 HTTP 请求报文。

在这里插入图片描述

请求头部用来描述客户端的基本信息,从而把客户端相关的信息告知服务器。比如:User-Agent 用来说明当前是什么类型的浏览器;Content-Type 用来描述发送到服务器的数据格式;Accept 用来描述客户端能够接收什么类型的返回内容;Accept-Language 用来描述客户端期望接收哪种人类语言的文本内容。
请求头部由多行 键/值对 组成,每行的键和值之间用英文的冒号分隔。

最后一个请求头字段的后面是一个空行,通知服务器请求头部至此结束。
请求消息中的空行,用来分隔请求头部与请求体。

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


响应消息就是服务器响应给客户端的消息内容,也叫作响应报文。

在这里插入图片描述

状态行由 HTTP 协议版本、状态码和状态码的描述文本 3 个部分组成,他们之间使用空格隔开;

在这里插入图片描述

响应头部用来描述服务器的基本信息。响应头部由多行 键/值对 组成,每行的键和值之间用英文的冒号分隔。

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers

在最后一个响应头部字段结束之后,会紧跟一个空行,用来通知客户端响应头部至此结束。
响应消息中的空行,用来分隔响应头部与响应体。

响应体中存放的,是服务器响应给客户端的资源内容。
在这里插入图片描述


HTTP的请求方法

序号方法描述
1GET(查询)发送请求来获得服务器上的资源,请求体中不会包含请求数据,请求数据放在协议头中。
2POST(新增)向服务器提交资源(例如提交表单或上传文件)。数据被包含在请求体中提交给服务器。
3PUT(修改)向服务器提交资源,并使用提交的新资源,替换掉服务器对应的旧资源。
4DELETE(删除)请求服务器删除指定的资源。
5HEADHEAD 方法请求一个与 GET 请求的响应相同的响应,但没有响应体。
6OPTIONS获取http服务器支持的http请求方法,允许客户端查看服务器的性能,比如ajax跨域时的预检等。
7CONNECT建立一个到由目标资源标识的服务器的隧道。
8TRACE沿着到目标资源的路径执行一个消息环回测试,主要用于测试或诊断。
9PATCH是对 PUT 方法的补充,用来对已知资源进行局部更新 。

在这里插入图片描述

HTTP响应状态码

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

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

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

在这里插入图片描述

完整的 HTTP 响应状态码,可以参考 MDN 官方文档 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status

2** 范围的状态码,表示服务器已成功接收到请求并进行处理。常见的 2** 类型的状态码如下:

状态码状态码英文名称中文描述
200OK请求成功。一般用于 GET 与 POST 请求
201Created已创建。成功请求并创建了新的资源,通常用于 POST 或 PUT 请求

3** 范围的状态码,表示表示服务器要求客户端重定向,需要客户端进一步的操作以完成资源的请求。常见的 3** 类型的状态码如下:

状态码状态码英文名称中文描述
301Moved Permanently永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302Found临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
304Not Modified未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源(响应消息中不包含响应体)。客户端通常会缓存访问过的资源。

4** 范围的状态码,表示客户端的请求有非法内容,从而导致这次请求失败。常见的 4** 类型的状态码如下:

状态码状态码英文名称中文描述
400Bad Request1、语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求。 2、请求参数有误。
401Unauthorized当前请求需要用户验证。
403Forbidden服务器已经理解请求,但是拒绝执行它。
404Not Found服务器无法根据客户端的请求找到资源(网页)。
408Request Timeout请求超时。服务器等待客户端发送的请求时间过长,超时。

5** 范围的状态码,表示服务器未能正常处理客户端的请求而出现意外错误。常见的 5** 类型的状态码如下:

状态码状态码英文名称中文描述
500Internal Server Error服务器内部错误,无法完成请求。
501Not Implemented服务器不支持该请求方法,无法完成请求。只有 GET 和 HEAD 请求方法是要求每个服务器必须支持的,其它请求方法在不支持的服务器上会返回501
503Service Unavailable由于超载或系统维护,服务器暂时的无法处理客户端的请求。

验证手机号的正则:const regex = /^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$/;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

roydon_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值