Ajax笔记

Ajax笔记,第1张


title: Ajax
categories: web前端学习笔记
date: 2022-03-01 15:27:51
tags:


什么是 AJAX ?

AJAX = 异步 JavaScript 和 XML。

AJAX 是一种用于创建快速动态网页的技术。

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。

URL地址 组成部分

通信协议,存放该资源的服务器名称,存放位置

客户端与服务器之间的通信过程,是 请求-处理-响应三个步骤

那么如何请求数据? -->使用对象XMLHttpRequest,简称xhr,是浏览器提供的js成员,通过xhr可以请求服务器上的数据资源。

var xhrObj = new XMLHttpRequest()

get是问服务器要资源,post是向服务器发送资源。

jquery中的ajax $.get()函数的用法

$.get(url,[data],[callback]),其中url是必须有的,data和callback是可有可无的

参数名参数类型说明
urlstring请求的资源地址
dataobject请求资源期间要携带的参数
callbackfunction请求成功时的回调函数
发起不带参数的请求
<button id='btn'>发起不带参数的请求button>
<script>
  $(function () {
    $('#btn').on('click', function () {
      $.get('http://www.liulongbin.top:3006/api/getbooks', function (res) {
        console.log(res)
      })
    })
  })

打开网页后,用f12查看请求情况,切换到network栏,然后切换到xhr栏,查看。

从headers可以看到请求的连接,以及请求的方式、请求的状态。

从response可以看到无格式的请求到的内容,有格式的则在preview栏。

发起带参数的请求
<button id="btn">发起带参数的get请求button>
  <script>
    $(function () {
      $('#btn').on('click', function () {
        $.get('http://www.liulongbin.top:3006/api/getbooks', { id: 1 }, function (res) {
          console.log(res);
        })
      })
    })
$.post()函数

和get相似。

$.post(url,[data],[callback]),其中url是必须有的,data和callback是可有可无的

参数名参数类型说明
urlstring提交数据的地址
dataobject要提交的数据
callbackfunction数据提交成功时的回调函数

代码ex:

<body>
  <button id="btn">用post提交数据button>
  <script>
    $(function () {
      $('#btn').on('click', function () {
        $.post('http://www.liulongbin.top:3006/api/addbook',//数据提交的url地址
          { bookname: '水浒传', author: '施耐庵', publisher: '上海图书出版社' },//要提交的数据
          function (res) {
            console.log(res);
          })
      })
    })
  script>
body>
$.ajax()函数
$.ajax({
   type: '', // 请求的方式,例如 GET 或 POST
   url: '',  // 请求的 URL 地址
   data: { },// 这次请求要携带的数据
   success: function(res) { } // 请求成功之后的回调函数
})
发起get请求
$.ajax({
   type: 'GET', // 请求的方式
   url: 'http://www.liulongbin.top:3006/api/getbooks',  // 请求的 URL 地址
   data: { id: 1 },// 这次请求要携带的数据
   success: function(res) { // 请求成功之后的回调函数
       console.log(res)
   }
})

发起post请求
$.ajax({
   type: 'post',
   url: 'http://www.liulongbin.top:3006/api/addbook',//数据提交的url地址
   data: { bookname: '我也不想知道', author: '司马迁', publisher: '上海图书出版社' },
   success: function (res) {
        console.log(res);
          }
        })

javascript trim()方法可以去除掉字符串头尾的空白符,其中空白符包括空格,tab,换行符等

form表单使用 form标签的属性
属性描述
actionurl地址规定当提交表单时,向何处发送表单数据
methodget或post规定以何种方式把表单数据提交到action URL
enctypeapplication/x-www-form-urlencoded multipart/form-data text/plain规定在发送表单数据之前如何对其进行编码
target_blank _self _parent _top framename规定在何处打开action URL
action

action属性的值应该是由后端提供的一个url地址,这个url地址专门负责接收表单提交过来的数据。如果form表单没有指定action属性值,那么action的默认值就是当前页面的url地址。提交表单后,页面会立刻跳转到action属性指定的url地址

method

默认情况下,method 的值为 get

get 方式适合用来提交少量的、简单的数据。
post 方式适合用来提交大量的、复杂的、或包含文件上传的数据。
在实际开发中,

表单的 post 提交方式用的最多,很少用 get。例如登录、注册、添加数据等表单 *** 作,都需要使用 post 方式来提交表单。

enctype
属性
application/x-www-form-urlencoded在发送前编码所有字符(默认)

| multipart/form-data | 不对字符编码。
在使用包含文件上传控件的表单时,必须使用该值。 |
| text/plain | 空格转换为 “+” 加号,但不对特殊字符编码。(很少用) |
不上传文件就直接不写这个属性就行

表单同步提交

表单同步提交是指点击submit按钮后,页面会直接跳转到action URL。

缺点是导致用户体验感差、页面之前的状态和数据都会丢失

解决方法:表单只负责采集数据,ajax负责将数据提交到服务器

通过ajax提交表单数据 监听表单提交事件
$('#form1').submit(function(e) {
   alert('监听到了表单的提交事件')
})

$('#form1').on('submit', function(e) {
   alert('监听到了表单的提交事件')
})
阻止表单默认提交行为
$('#form1').submit(function(e) {
   // 阻止表单的提交和页面的跳转
   e.preventDefault()
})

$('#form1').on('submit', function(e) {
   // 阻止表单的提交和页面的跳转
   e.preventDefault()
})
快速获得表单中的数据

serialize()函数

$(selector).serialize()

serialize()函数可以一次性获得表单中的所有数据

<form id="form1">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <button type="submit">提交button>
form>
$('#form1').serialize()
// 调用的结果:
// username=用户名的值&password=密码的值

注意:在使用 serialize() 函数快速获取表单数据时,必须为每个表单元素添加 name 属性。

jquery对象转化为原生dom对象->使用 jquery对象[0]

模板引擎的使用

当我们想要把某个ui结构渲染到页面上时,一般情况下会采用字符串拼接的方式。但是如果ui结构比较复杂,此时对于单引号的使用就要格外注意,而且需求一旦发生变化,修改起来也十分困难。由此我们引入了模板引擎来解决这一问题。

var rows = []
$.each(res.data, function (i, item) { // 循环拼接字符串
    rows.push('
  • '+ item.content +'评论时间:'+ item.time +'评论人:'+ item.username +'
  • '
    ) }) $('#cmt-list').empty().append(rows.join('')) // 渲染列表的UI结构

    模板引擎可以根据我们指定的模板结构和数据自动生成一个完整的html页面

    模板引擎使用步骤:

    1.导入模板引擎

    导入后,在windows全局,则多了一个函数,叫做template("模板的id",需要渲染的数据对象)

    <script src="./lib/template-web.js">script>
    

    2.定义需要渲染的数据

    var data = { name: 'zs' ,age:20}
    

    3.定义模板

    
      <script type="text/html" id="tpl-user">
        <h1>{{name}}    ------    {{age}}</h1>
      script>
    

    4.调用template函数

     var htmlStr = template('tpl-user', data)
    

    5.渲染html结构

    $('#container').html(htmlStr)
    

    全部代码:

    <head>
    
      
      <script src="./lib/template-web.js">script>
      <script src="./lib/jquery.js">script>
    head>
    <body>
    
      <div id="container">div>
    
      
      
      <script type="text/html" id="tpl-user">
        <h1>{{name}}    ------    {{age}}</h1>
      script>
    
      <script>
      // 2. 定义需要渲染的数据
        var data = { name: 'zs', age: 20, test: '测试原文输出', flag: 1, hobby: ['吃饭', '睡觉', '写代码'], regTime: new Date() }
    
        // 4. 调用 template 函数
        var htmlStr = template('tpl-user', data)
        console.log(htmlStr)
        // 5. 渲染HTML结构
        $('#container').html(htmlStr)
      script>
    body>
    
    标准语法 输出
    {{value}}//变量的输出
    {{obj.key}}//对象属性
    {{obj['key']}}
    {{a ? b : c}}//三元表达式
    {{a || b}}//逻辑
    {{a + b}}//加减乘除等表达式
    
    原文输出
    {{@ value }}
    

    如果要输出的 value 值中,包含了 HTML 标签结构,则需要使用原文输出语法,才能保证 HTML 标签被正常渲染

    条件输出
    {{if value}} 按需输出的内容 {{/if}}
    
    {{if v1}} 按需输出的内容 {{else if v2}} 按需输出的内容 {{/if}}
    
    循环输出
    {{each arr}}
        {{$index}} {{$value}}
    {{/each}}
    
    过滤器

    {{value | filterName}}

    定义过滤器的基本语法:

    template.defaults.imports.filterName = function(value){
     // return处理的结果
    }
    

    ex:格式化时间过滤器

      <div id="container">div>
      <script type="text/html" id="tpl-user">
      <h3>{{regTime | dateFormat}}</h3>
      script>
    
      <script>
        template.defaults.imports.dateFormat = function (date) {
          var y = date.getFullYear()
          var m = date.getMonth() + 1
          var d = date.getDate()
          return y + '-' + m + '-' + d
        }
    
        var data = {  regTime: new Date() }
        var html = template('tpl-user', data)
        $('#container').html(html)
      script>
    
    正则与字符串 *** 作

    exec函数用于检索字符串中的正则表达式的匹配,如果字符串中有匹配的值,则返回一个数组,其中存储匹配的结果,否则返回null

    RegExpObject.exec(string)
    

    下面以此例来解释exec函数返回的数组的内容

    var str = 'hello'
    var pattern = /o/
    console.log(pattern.exec(str)) 
    

    1. 0: “o” 与正则表达式相匹配的文本
    2. groups: undefined 存储着所有的命名捕获组。
    3. index: 4 index 属性声明的是匹配文本的第一个字符的位置
    4. input: “hello” 存放的是被检索的字符串 string
    5. length: 1 数组长度
    xhr的使用 发起get请求
    //创建xhr对象
    var xhr = new XMLHttpRequest()
    //调用open函数,指定请求方式与url地址
    xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks?publisher=北京图书出版社')//?后面是带的参数 这种在 URL 地址后面拼接的参数,叫做查询字符串。
    
    //调用send函数,发起ajax请求
    xhr.send()
    //监听
    xhr.onreadystatechange = function () {
        // 监听 xhr 对象的请求状态 readyState ;与服务器响应的状态 status
      if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
        console.log(typeof xhr.responseText);
        console.log(JSON.parse(xhr.responseText));//将json字符串转换成JavaScript对象
      }
    }
    

    readyState属性

    状态描述
    0unsentXmlHttpRequest对象已被创建,但尚未调用open方法
    1openedopen方法已经被调用
    2headers_receivedsend方法已经被调用
    3loading数据接收中,此时 response 属性中已经包含部分数据。
    4doneAjax 请求完成,这意味着数据传输已经彻底完成或失败。
    url编码

    url地址中不允许出现中文字符,如果url中需要包含中文字符,那么必须对其进行编码。

    浏览器提供了 URL 编码与解码的 API,分别是:
    encodeURI() 编码的函数
    decodeURI() 解码的函数

    发起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)
        }
    }
    
    xhr level2

    新功能

    • 可以设置 HTTP 请求的时限
    • 可以使用 FormData 对象管理表单数据
    • 可以上传文件
    • 可以获得数据传输的进度信息
    设置HTTP请求时限
    xhr.timeout = 3000//设置http请求的时限为3000毫秒
    xhr.ontimeout = function(event){
    alert('请求超时!')
    }
    
    FormData对象管理表单数据
          // 1. 新建 FormData 对象
          var fd = new FormData()
          // 2. 为 FormData 添加表单项
          fd.append('uname', 'zs')
          fd.append('upwd', '123456')
          // 3. 创建 XHR 对象
          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));
          }
        }
    

    获取表单元素:

    var form = document.querySelector('#form1')
    form.addEventListener('submit', function (e) {
      e.preventDefault()//阻止默认提交行为
      // 创建formdata,快速获得表单中的数据
      var fd = new FormData(form)
      var xhr = new XMLHttpRequest()
      xhr.open('post', 'http://www.liulongbin.top:3006/api/formdata')
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
      xhr.send(fd)
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(JSON.parse(xhr.responseText));
        }
      }
    })
    
    上传文件

    实现步骤

    1. 定义ui结构
    2. 验证是否选择了文件
    3. 向Formdata中追加文件
    4. 发起上传文件的请求
    5. 监听onreadystatechange事件
        var btnUpload = document.querySelector('#btnUpload')
        btnUpload.addEventListener('click', function () {
          //获取到选择的列表
          var files = document.querySelector('#file1').files
          if (files.length <= 0)
            return alert('请选择要上传的文件!')
          var fd = new FormData()
          fd.append('avatar', files[0])
    
          // 1. 创建 xhr 对象
          var xhr = new XMLHttpRequest()
          // 显示文件的上传进度
          xhr.upload.onprogress = function (e) {
            if (e.lengthComputable) {
              var percentComplete = Math.ceil((e.loaded / e.total) * 100)
              console.log(percentComplete)
              $('#percent').attr('style', 'width:' + percentComplete + '%')
                // 3. 显示当前的上传进度百分比
                .html(percentComplete + '%')
            }
          }
          //进度条完成以后设置样式
          xhr.upload.onload = function () {
            $('#percent')
              // 移除上传中的类样式
              .removeClass()
              // 添加上传完成的类样式
              .addClass('progress-bar progress-bar-success')
          }
          // 2. 调用 open 函数,指定请求类型与URL地址。其中,请求类型必须为 POST
          xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
          // 3. 发起请求
          xhr.send(fd)
    
          xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
              var data = JSON.parse(xhr.responseText)
    
              if (data.status === 200) { // 上传文件成功
                // 将服务器返回的图片地址,设置为  标签的 src 属性
                document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
              } else { // 上传文件失败
                console.log(data.message)
              }
            }
          }
        })
    
    axios

    概念:axios是专注网络数据请求的库,相比于XHR对象,axios简单易用

    发起get请求
     axios.get('url', { params: { /*参数*/ } }).then(callback)
    

    ex:

     // 请求的 URL 地址
     var url = 'http://www.liulongbin.top:3006/api/get'
     // 请求的参数对象
     var paramsObj = { name: 'zs', age: 20 }
     // 调用 axios.get() 发起 GET 请求
     axios.get(url, { params: paramsObj }).then(function(res) {
         // res.data 是服务器返回的数据
         var result = res.data
         console.log(res)
     })
    
    发起post请求
     axios.post('url', { /*参数*/ }).then(callback)
    

    ex:

     // 请求的 URL 地址
     var url = 'http://www.liulongbin.top:3006/api/post'
     // 要提交到服务器的数据
     var dataObj = { location: '北京', address: '顺义' }
     // 调用 axios.post() 发起 POST 请求
     axios.post(url, dataObj).then(function(res) {
         // res.data 是服务器返回的数据
         var result = res.data
         console.log(result)
     })
    
    直接使用axios发起请求
       //get
     axios({
         method: 'GET',
         url: 'http://www.liulongbin.top:3006/api/get',
         params: { // GET 参数要通过 params 属性提供
             name: 'zs',
             age: 20
         }
     }).then(function(res) {
         console.log(res.data)
     })
    
       
     axios({
         method: 'POST',
         url: 'http://www.liulongbin.top:3006/api/post',
         data: { // POST 数据要通过 data 属性提供
             bookname: '程序员的自我修养',
             price: 666
         }
     }).then(function(res) {
         console.log(res.data)
     })
    
    
    JSON

    概念:JSON 的英文全称是 JavaScript Object Notation,即“JavaScript 对象表示法”。简单来讲,JSON 就是 Javascript 对象和数组的字符串表示法,它使用文本表示一个 JS 对象或数组的信息,因此,JSON 的本质是字符串。

    json的对象结构

    {key:value,key:value,·····} 其中属性名必须是使用英文的双引号包裹的字符串,如果属性值也是字符串类型的,则必须也用双引号包裹

    ex:

    {
        "name": "zs",
        "age": 20,
        "gender": "男",
        "address": null,
        "hobby": ["吃饭", "睡觉", "打豆豆"]
    }
    
    json的数组结构
    [ "java", "python", "php" ]
    [ 100, 200, 300.5 ]
    [ true, false, null ]
    [ { "name": "zs", "age": 20}, { "name": "ls", "age": 30} ]
    [ [ "苹果", "榴莲", "椰子" ], [ 4, 50, 5 ] ]
    

    注意:

    • json中不能写注释
    • json的最外层必须是对象或者数组格式
    • 不能使用undefined或函数作为json的值

    json用于在计算机与网络之间存储和传输数据

    json的本质是用字符串来表达JavaScript对象/数组数据

    json和js对象的互转

    json转js ->JSON.parse() 又称为json反序列化

    js转json ->JSON.stringify() 又称为json序列化

    同源策略

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

    同源策略是浏览器提供的一个安全功能,它规定A网站的JavaScript不允许和非同源的网站B之间 进行交互。

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

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

    那么如何实现跨域请求?有两种解决方案,JSONP和CORS

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

    JSONP

    JSONP是JSON的一种使用方式,可用通过来解决主流浏览器的跨域数据访问问题

    实现原理:

    因为浏览器受同源策略的影响,网页无法通过ajax请求非同源的接口数据。但是script标签不受浏览器同源策略影响,因此可以通过src属性,来请求非同源的js脚本。

    所以JSONP就是利用这个src属性,来请求跨域的数据接口,共通过函数调用的形式,接收跨域接口响应回来的数据

    缺点:jsonp只支持get请求,不支持post请求

    jsonp和ajax之间没有任何关系,不能把jsonp请求数据的方式叫做Ajax。因为jsonp并没有使用xhr对象

    jquery中的jsonp
     $.ajax({
       url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
        // 如果要使用 $.ajax() 发起 JSONP 请求,必须指定 datatype 为 jsonp
        dataType: 'jsonp',
        success: function(res) {
           console.log(res)
        }
     })
    

    默认情况下,使用 jQuery 发起 JSONP 请求,会自动携带一个callback=jQueryxxx 的参数,jQueryxxx 是随机生成的一个回调函数名称。

    jsonp的参数和回调函数的名称是可以自定义的

    $.ajax({
        url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
        dataType: 'jsonp',
        // 发送到服务端的参数名称,默认值为 callback
        jsonp: 'callback',
        // 自定义的回调函数名称,默认值为 jQueryxxx 格式
        jsonpCallback: 'abc',
        success: function(res) {
           console.log(res)
        }
     })
    

    jQuery 中的 JSONP,也是通过