Ajax复习(62nd)

本文详细介绍了Ajax的基础知识,包括其解决的传统网站问题、工作原理、应用场景和实现步骤。同时,讲解了JSON的结构和在Ajax中的作用,以及如何在JavaScript中进行JSON对象与字符串的相互转化。此外,文章还探讨了GET和POST请求的参数处理,并封装了简单的Ajax函数。最后,提到了跨域问题,解析了JSONP的工作原理和实现跨域数据请求的方法。
摘要由CSDN通过智能技术生成

1、 Ajax 基础

1.1 传统网站中存在的问题

1、网速慢的情况下,页面加载时间长,用户只能等待
2、表单提交后,如果一项内容不合格,需要重新填写所有表单内容
3、页面跳转,重新加载页面,造成资源浪费,增加用户等待时间

1.2 Ajax 概述

1、Ajax 的全称是 Asynchronous Javascript And XML(异步 JavaScript 和 XML)

2、Ajax的原理简单来说通过XMLHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用JavaScript来操作DOM而更新页面

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

流程图:

在这里插入图片描述
浏览器可以发送HTTP请求后,接着做其他事情,等收到XHR返回来的数据再进行操作

1.3 Ajax 应用场景

如:
1、用户名检测:注册用户时,通过 ajax 的形式,动态检测用户名是否被占用
2、搜索提示:当输入搜索关键字时,通过 ajax 的形式,动态加载搜索提示列表
3、数据分页显示:当点击页码值的时候,通过 ajax 的形式,根据页码值动态刷新表格的数据
4、数据的增删改查:数据的添加、删除、修改、查询操作,都需要通过 ajax 的形式,来实现数据的交互

2、Ajax 运行原理及实现

2.1 Ajax 运行原理

Ajax 相当于浏览器发送请求与接收响应的代理人,以实现在不影响用户浏览页面的情况下,局部更新页面数据,从而提高用户体验。
在这里插入图片描述

2.2 Ajax 实现步骤

实现 Ajax异步交互需要服务器逻辑进行配合,需要完成以下步骤:

1、创建 Ajax的核心对象 XMLHttpRequest对象

2、通过 XMLHttpRequest 对象的 open() 方法与服务端建立连接

3、构建请求所需的数据内容,并通过XMLHttpRequest 对象的 send() 方法发送给服务器端

4、通过 XMLHttpRequest 对象提供的 onreadystatechange 事件监听服务器端的通信状态

5、接受并处理服务端向客户端响应的数据结果

6、将处理结果更新到 HTML页面中

1、创建 Ajax 对象

使用 XMLHttpRequest 构造函数实例化创建一个 xhr(“小黄人”)。

var xhr = new XMLHttpRequest();

2、告诉 Ajax 请求方式以及请求地址

以何种方式发送请求,向哪发送请求。

// xhr.open('method', 'url')
xhr.open('get', 'http://www.example.com');

3、发送请求

xhr.send();

4、获取服务器端给与客户端的响应数据

响应受到网络环境的影响,发送请求以后不能直接去接收数据(例如网络拥挤导致服务器延迟响应),而是要使用 onreadystatechange 事件监听服务器端的通信状态,主要监听的属性为XMLHttpRequest.readyStateresponseText 是服务器响应的数据内容。

xhr.onreadystatechange = function () {
    // 当 ajax 状态码为 4,意味着服务器成功接收到请求
    // 当 http 状态码为 200,意味着客户端成功接收到数据,交易成功
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
}

关于XMLHttpRequest.readyState属性有五个状态,如下图显示
在这里插入图片描述
客户端(浏览器)向服务器端发起请求,服务器接收到请求信息,然后向客户端返回一个包含 HTTP 状态码的信息头(server header)用以响应浏览器的请求。

HTTP常见状态码:

200:请求成功。
301:资源被永久转移到其他 URL
404:请求的资源不存在
500:服务器端内部错误

2.3 JSON

1、JSON的概念

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

因此,JSON的本质是字符串。

2、JSON的两种结构

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

1、对象结构:

对象结构在JSON中表示为{ }括起来的内容。

数据结构为{ key: value, key: value, .. }的键值对结构。

其中,key 必须是使用英文的双引号包裹的字符串,value 的数据类型可以是数字、字符串、布尔值、null、 数组、对象6种类型。

2、数组结构:

数组结构在JSON中表示为[ ]括起来的内容。

数据结构为[ "java", "javascript", 30, true ..]

数组中数据的类型可以是数字、字符串、布尔值、null、 数组、对象6种类型。

2.4 JSON和JS对象的相互转化

1、在真实的项目中,服务器端大多数情况下会以 JSON 对象作为响应数据的格式。
2、当客户端拿到响应数据时,要将 JSON 数据和 HTML 字符串进行拼接,然后将拼接的结果展示在页面中。
3、通过 xhr.getResponseHeader('Content-Type') 可获取服务器响应数据的形式,一般有两种:

	1、JSON 对象形式:`application/json`
	返回的 `xhr.responseText` 为 JSON 对象字符串,需要转换为 JSON 对象。
	2、普通字符串形式:`text/hrml`

在 http 请求与响应的过程中,无论是请求参数还是响应内容,如果是对象类型,最终都会被转换为对象字符串进行传输。我们往往使用 JSON.parse() 方法将该对象字符串转换为对象。

将 json 字符串转换为JS对象,使用JSON.parse()方法

JSON.parse() 	// 将 json 字符串转换为json对象
xhr.onload = function () {
    var responseText = JSON.parse(xhr.responseText)
    console.log(responseText);
}

要实现从JS对象转换为JSON字符串,使用JSON.stringify()方法

var json = JSON.stringify({a:'Hello', b: 'World' });
//结果是' {"a": "Hello", "b":"World"} '

2.5 get请求/post请求带参数

1、GET请求

//get.html
btn.onclick = function () {	
   	// 创建ajax对象
   	var xhr = new XMLHttpRequest();
   	// 获取用户在文本框中输入的值
   	var nameValue = username.value;
   	var ageValue = age.value;
   	// 拼接请求参数
   	var params = 'username=' + nameValue + '&age=' + ageValue;
   	// 调用open函数
   	xhr.open('get', 'http://localhost:3000/test?' + params);
   	// 发送请求
   	xhr.send();
   	// 获取服务器端响应的数据
   	xhr.onreadystatechange = function () {
    // 当 ajax 状态码为 4,意味着服务器成功接收到请求
    // 当 http 状态码为 200,意味着客户端成功接收到数据,交易成功
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
 }

2、POST请求

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('name=zhangsan&age=20');

举例:

// 拼接参数
let params = 'username=' + nameValue + '&age=' + ageValue;
// 设置post请求
xhr.open('post', 'http://localhost:3001/post');
// 设置请求参数格式的类型(post方式必须设置,固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// post请求的参数写在 send 方法里面
xhr.send(params);
//监听事件
xhr.onreadystatechange = function () {
    // 当 ajax 状态码为 4,意味着服务器成功接收到请求
    // 当 http 状态码为 200,意味着客户端成功接收到数据,交易成功
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }

2.6 两种获取服务器端响应方式的区别

在这里插入图片描述

3、封装自己的Ajax

1、简单封装一个 GET Ajax 请求函数

function ajax(options) {
    let xhr = new XMLHttpRequest();
    xhr.open(options.type, options.url);
    xhr.send();
    xhr.onload = function () {
    	//把服务器响应的数据xhr.responseText传给success函数
        options.success(xhr.responseText);
    }
}
//使用部分
ajax({
    type: 'get',
    url: 'http://localhost:3001/first',
    // 通过 success 函数接收返回的响应数据,并进行下一步处理
    success: function (data) {
        console.log(data);
    }
});

2、完整版本

//封装一个ajax请求
function ajax(options) {
    //创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()


    //初始化参数的内容
    options = options || {}
    options.type = (options.type || 'GET').toUpperCase()
    options.dataType = options.dataType || 'json'
    const params = options.data

    //发送请求
    if (options.type === 'GET') {
        xhr.open('GET', options.url + '?' + params, true)
        xhr.send(null)
    } else if (options.type === 'POST') {
        xhr.open('POST', options.url, true)
        xhr.send(params)

    //接收请求
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            let status = xhr.status
            if (status >= 200 && status < 300) {
                options.success && options.success(xhr.responseText, xhr.responseXML)
            } else {
                options.fail && options.fail(status)
            }
        }
    }
}

使用方式如下

ajax({
    type: 'post',
    dataType: 'json',
    data: {},
    url: 'https://xxxx',
    success: function(text,xml){//请求成功后的回调函数
        console.log(text)
    },
    fail: function(status){请求失败后的回调函数
        console.log(status)
    }
})

4、FormData

4.1 H5新增FormData 对象

H5新增FormData 对象,模拟表单操作,在有多个参数的 Ajax 请求中,例如名字、密码、年龄、性别等,都要使用 DOM 获取元素,然后又要按照规则拼接参数。传统 Ajax 也不能传送二进制文件。使用 FormData 对象可以解决这些问题。

FormData 的作用:

1、模拟 HTML 表单,相当于将 HTML 表单映射成表单对象,自动将表单对象中的数据拼接成请求参数的格式。
2、异步上传二进制文件

4.2 FormData 对象的使用

1、准备 HTML 表单

<form id="form">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <input type="button"/>
</form>

2、将 HTML 表单转化为 FormData 对象

var form = document.getElementById('form'); 
var formData = new FormData(form);

3、提交表单对象

var xhr = new XMLHttpRequest();
xhr.open('post', 'http://localhost:3001/post');
xhr.send(formData);

注意:

FormData 对象不能用于 get 请求,因为对象需要被传递到 send 方法中,而 get 请求方式的请求参数只能放在请求地址的后面。

4.3 FormData 二进制文件上传

<input type="file" id="file"/>
var file = document.getElementById('file')
// 当用户选择文件的时候
file.onchange = function () {
    // 创建空表单对象
    var formData = new FormData();
    // 将用户选择的二进制文件追加到表单对象中
    formData.append('attrName', this.files[0]);
    // 配置ajax对象,请求方式必须为post
    xhr.open('post', 'www.example.com');
    xhr.send(formData);
}

4.4 FormData 文件上传展示

 // 当用户选择文件的时候
file.onchange = function () {
    // 文件上传过程中持续触发onprogress事件
    xhr.upload.onprogress = function (ev) {
        // 当前上传文件大小/文件总大小 再将结果转换为百分数
        // 将结果赋值给进度条的宽度属性 
        bar.style.width = (ev.loaded / ev.total) * 100 + '%';
    }
}

4.5 FormData 文件上传图片即时预览

xhr.onload = function () {
    var result = JSON.parse(xhr.responseText);
    var img = document.createElement('img');
    img.src = result.src;
    img.onload = function () {
        document.body.appendChild(this);
    }
}

5、axios

1、什么是axios

1、axios专注于网络数据请求的库。

2、相比于原生的XMLHttpRequest对象,axios 简单易用。

3、相比于jQuery, axios 更加轻量化,只专注于网络数据请求。

2、axios发起GET 请求

语法:

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

具体的请求示例如下:

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

3、axios发起POST请求

语法:

axios.post('url', {params:{/*参数*/}}).then (callback)

直接使用axios发起请求
axios也提供了类似于jQuery中$.ajax()的函数,语法如下:

axios ({
method: '请求类型’,
url: '请求的URL地址',
data: { /*POST数据*/},
params:{ /*GET参数*/}
}).then(callback)

6、同源与跨域

1、同源

如果两个页面拥有相同的协议、域名和端口,那么这两个页面就属于同一个源,其中只要有一个不相同,就是不同源。

同源策略,它是由 Netscape 提出的一个著名的安全策略,现在所有支持 JavaScript 的浏览器都会使用这个策略。
浏览器规定,A网站的JavaScript,不允许和非同源的网站C之间,进行资源的交互

2、跨域

1.同源指的是两个URL的协议、域名、端口一致,
反之,有一项不相同,则是跨域。

2.出现跨域的根本原因:
浏览器的同源策略不允许非同源的URL之间进行资源的交互。

3、浏览器对跨域请求的拦截

在这里插入图片描述
浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器拦截,无法被页面获取到!

4、如何实现跨域数据请求

现如今,实现跨域数据请求,最主要的两种解决方案,分别是JSONP和CORS。

1.JSONP:
出现的早,兼容性好(兼容低版本IE) 。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持GET求,不支持POST请求。

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

5、使用 JSONP 解决同源限制问题

JSONP 是 json with padding 的缩写,它不属于 Ajax 请求,但它可以模拟 Ajax 请求。
使用 JSONP,我们可以绕过同源政策,从而实现跨域读取数据。
我们知道 script 标签可以引入其他 JS 文件,比如 CDN jQuery链接:

<script src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>

JSONP 原理:

1、实际上 script 中的 src 属性中可以放的不止 JS 这一种文件类型,也可以是一个服务器地址。script 处理 JS 文件的原理,首先加载该地址中的 JS 文件,然后从头到尾执行一遍该文件的内容。

2、所以,如果 src 指向服务器端里的内容是一段为函数的字符串,那么该函数在当前页面将会被执行。

3、那么服务器可以返回一个 “函数字符串”,然后客户端执行提前准备好的该函数内容。

基本步骤:

1、提前定义好 fn 函数,在 fn 函数内部对服务器端返回的数据进行处理

function fn (data) {
    console.log(data);
}

2、将不同源的服务器端请求地址写在 script 标签的 src 属性中。

<script src="www.example.com"></script>

3、服务器端响应数据必须是一个函数的调用,会被当做JavaScript代码来执行,真正要发送给客户端的数据需要作为函数调用的参数。
例如,node express 服务器端(app.js):

const data = 'fn({name: "张三", age: "20"})';
res.send(data);

6、封装自己的myJsonp

/* jsonp的实现原理: 通过script标签的src属性请求跨域的数据接口,并通过函数调用的形式,接收跨域接口响应回来的数据
 */
 
/**
 *
 * @param {string} url src的url地址
 * @param {object} data 数据对象
 * @param {function} callback  返回函数
 */
function myJsonp(options) {
  /* 1.首先动态创建script标签 */
  var script = document.createElement("script");
  //1.1 把数据对象转换为查询字符串
  var qs = resolveData(options.data);
  // 1.2动态生成函数名
  var jsonpName = "myJsonp" + Math.random().toString().substr(2);
  //1.3将当前文件名放到window里
  window[jsonpName] = function (res) {
    //把结果回掉出去
    options.success && options.success(res);
    //删除window中的函数名
    delete window[jsonpName];
  };
  /* 2.给src设置url和参数 */
  script.src = options.url + "?callback=" + jsonpName + "&" + qs;
  /* 3.添加到html */
  document.querySelector("head").appendChild(script);
  /* 4.加载完毕后删除script标签    使用监听 */
  script.onload = function () {
    document.querySelector("head").removeChild(script);
  };
}
//把数据对象转换为查询字符串
function resolveData(data) {
  var rows = [];
  for (var k in data) {
    rows.push(k + "=" + data[k]);
  }
  return rows.join("&");
}

测试代码:

<button>提交</button>
    <script>
      document.querySelector("button").addEventListener("click", function () {
        myJsonp({
          url: "http://www.liulongbin.top:3006/api/jsonp",
          data: {
            uname: "chenxuan",
            age: "12",
            hobby: "eat",
          },
          success: function (res) {
            console.log(res);
          },
        });
      });
    </script>

jsonp的缺点:JSONP 只支持 GET 数据请求,不支持 post 请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值