🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## AJAX AJAX 即 Asynchronous JavaScript and XML,异步的 JavaScript 和 XML。使用 AJAX 可以无刷新地向服务端发送请求接收服务端响应,并更新页面。 ### 原生 JS 实现 AJAX JS 实现 AJAX 主要基于浏览器提供的 XMLHttpRequest(XHR)类,所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。 **获取XMLHttpRequest对象** ``` // 获取XMLHttpRequest对象 var xhr = new XMLHttpRequest(); ``` 如果需要兼容老版本的 IE \(IE5, IE6\) 浏览器,则可以使用 ActiveX 对象: ``` var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { xhr = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } ``` **发送一个 HTTP 请求** 接下来,我们需要打开一个URL,然后发送这个请求。分别要用到 XMLHttpRequest 的 open\(\) 方法和 send\(\) 方法。 ``` // GET var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { xhr = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } if (xhr) { xhr.open('GET', '/api?username=admin&password=root', true); xhr.send(null); } ``` ``` // POST var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { xhr = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } if (xhr) { xhr.open('POST', '/api', true); // 设置 Content-Type 为 application/x-www-form-urlencoded // 以表单的形式传递数据 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('username=admin&password=root'); } ``` open\(\) 方法有三个参数: * open\(\) 的第一个参数是 HTTP 请求方式 – GET,POST,HEAD 或任何服务器所支持的您想调用的方式。按照HTTP规范,该参数要大写;否则,某些浏览器\(如Firefox\)可能无法处理请求。有关HTTP请求方法的详细信息可参考 [https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html](http://link.zhihu.com/?target=https%3A//www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) * 第二个参数是请求页面的 URL。由于同源策略(Same origin policy)该页面不能为第三方域名的页面。同时一定要保证在所有的页面中都使用准确的域名,否则调用 open\(\) 会得到 permission denied 的错误提示。 * 第三个参数设置请求是否为异步模式。如果是 TRUE,JavaScript 函数将继续执行,而不等待服务器响应。这就是 AJAX 中的 A。 如果第一个参数是 GET,则可以直接将参数放在 url 后面,如:[http://nodejh.com/api?name=admint&password=root](http://link.zhihu.com/?target=http%3A//nodejh.com/api%3Fname%3Dadmint%26password%3Droot)。 如果第一个参数是 POST,则需要将参数写在 send\(\) 方法里面。send\(\) 方法的参数可以是任何想送给服务器的数据。这时数据要以字符串的形式送给服务器,如:name=admint&password=root。或者也可以传递 JSON 格式的数据: ``` // 设置 Content-Type 为 application/json xhr.setRequestHeader('Content-Type', 'application/json'); // 传递 JSON 字符串 xhr.send(JSON.stringify({ username:'admin', password:'root' })); ``` 如果不设置请求头,原生 AJAX 会默认使用 Content-Type 是 text/plain;charset=UTF-8 的方式发送数据。 关于 Content-Type 更详细的内容,将在以后的文章中解释说明。 **处理服务器的响应** 当发送请求时,我们需要指定如何处理服务器的响应,我们需要用到 onreadystatechange 属性来检测服务器的响应状态。使用 onreadystatechange 有两种方式,一是直接 onreadystatechange 属性指定一个可调用的函数名,二是使用一个匿名函数: ``` // 方法一 指定可调用的函数 xhr.onreadystatechange = onReadyStateChange; function onReadyStateChange() { // do something } // 方法二 使用匿名函数 xhr.onreadystatechange = function(){ // do the thing }; ``` 接下来我们需要在内部利用 readyState 属性来获取当前的状态,当 readyState 的值为 4,就意味着一个完整的服务器响应已经收到了,接下来就可以处理该响应: ``` // readyState的取值如下 // 0 (未初始化) // 1 (正在装载) // 2 (装载完毕) // 3 (交互中) // 4 (完成) if (xhr.readyState === 4) { // everything is good, the response is received } else { // still not ready } ``` 完整代码如下: ``` // POST var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { xhr = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } if (xhr) { xhr.onreadystatechange = onReadyStateChange; xhr.open('POST', '/api', true); // 设置 Content-Type 为 application/x-www-form-urlencoded // 以表单的形式传递数据 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('username=admin&password=root'); } // onreadystatechange 方法 function onReadyStateChange() { // 该函数会被调用四次 console.log(xhr.readyState); if (xhr.readyState === 4) { // everything is good, the response is received if (xhr.status === 200) { console.log(xhr.responseText); } else { console.log('There was a problem with the request.'); } } else { // still not ready console.log('still not ready...'); } } ``` 然而需要注意的是,IE对 onload 属性的支持并不友好。除了 onload 还有以下几个属性也可以用来监测响应状态: * onloadstart * onprogress * onabort * ontimeout * onerror * onloadend