关于前端:原生Ajax使用详解ES5

49次阅读

共计 8326 个字符,预计需要花费 21 分钟才能阅读完成。

Ajax 的实现

// 1. 创立 Ajax 对象
 let xhr = new XMLHttpRequest();
​
// 2. 指定 Ajax 发送申请的形式与门路。参数 1: 申请办法;参数 2: 申请门路。xhr.open('get', 'http://localhost:3000/first');
​
// 3. 发送申请
 xhr.send();
​
// 4. 获取服务器响应到客户端的数据
 xhr.onload = function(){console.log(xhr.responseText);
 }

Ajax 的实现(服务器端)

// 引入 express 框架
const express = require('express');
// 门路解决模块
const path = require('path');
// 创立 web 服务器
const app = express();
// 动态资源拜访服务性能
app.use(express.static(path.join(__dirname, 'public')));
​
// 监听端口
app.listen(3000);
// 控制台提醒输入
console.log('服务器启动胜利');

解决服务端响应的 JSON 数据

客户端

// 1. 创立 Ajax 对象

 let xhr = new XMLHttpRequest();
​
// 2. 指定 Ajax 发送申请的形式与门路。参数 1: 申请办法;参数 2: 申请门路。xhr.open('get', 'http://localhost:3000/jsonGet');
​
// 3. 发送申请
 xhr.send();
​
// 4. 获取服务器响应到客户端的数据
 xhr.onload = function(){
 // 将 JSON 字符串转换为 JSON 对象
 console.log(JSON.parse(xhr.responseText));
 }

服务器端

app.get('/jsonGet', (req, res)=>{res.send({'name': 'Jeff'});
})

JSON 字符串 转换为 JSON 对象

JSON.parse(str)

JSON 对象 转化为 JSON 字符

JSON.stringify(obj)

GET 申请

// 1. 创立 Ajax 对象
 let xhr = new XMLHttpRequest();
​
// 2. 指定 Ajax 发送申请的形式与门路。参数 1: 申请办法;参数 2: 申请门路。//xhr.open('get', 'http://localhost:3000/get?name=Jeff&age=20');
 let params = `http://localhost:3000/get?username=${nameValue}&age=${ageValue}`;
 xhr.open('get', params);
​
// 3. 发送申请
 xhr.send();
​
// 4. 获取服务器响应到客户端的数据
 xhr.onload = function(){console.log(xhr.responseText);
 }

** 服务器端 **

get 申请参数获取 **req.query**

app.get('/get', (req, res)=>{res.send(req.query);
})

POST 申请

// 1. 创立 Ajax 对象
 let xhr = new XMLHttpRequest();
​
// 2. 指定 Ajax 发送申请的形式与门路。参数 1: 申请办法;参数 2: 申请门路。xhr.open('post', 'http://localhost:3000/post');
​
// 3. 设置申请参数格局的类型(POST 申请必须要设置)xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
​
// 4. 发送申请
 xhr.send(`username=${nameValue}&age=${ageValue}`);
​
// 5. 获取服务器响应到客户端的数据
 xhr.onload = function(){console.log(xhr.responseText);
 }

服务器端

const bodyParser = require('body-parser'); // 用于接管客户端传递的参数(req.body)app.use(bodyParser.urlencoded()); // 用于解析 application/x-www-form-urlencoded 格局的参数
​
app.post('/post', (req, res)=>{res.send(req.body);
})

申请参数传递

GET 申请形式

xhr.open('get', 'http://www.example.com?name=zhangsan&age=20');

POST 申请形式

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

POST申请参数的格局

  1. application/x-www-form-urlencoded
  2. application/json
// 在申请头中指定 Content-Type 属性的值是 application/json,通知服务器端以后申请参数的格局是 json
xhr.send({name: 'zhangsan', age: '20', sex: '男'});
xhr.send(JSON.stringify({name: 'Jeff', age: '20'}));

留神:get 申请是不能提交 json 对象数据格式的,传统网站的表单提交也是不反对 json 对象数据格式的。

服务器端

const bodyParser = require('body-parser');        // 用于接管客户端传递的参数(req.body)app.use(bodyParser.json());        // 用于解析 application/json 格局的参数

app.post('/post', (req, res)=>{res.send(req.body);
})

Ajax 状态码

  • 0:申请未初始化(还没有调用 open())
  • 1:申请曾经建设,然而还没有发送(还没有调用 send())
  • 2:申请曾经发送
  • 3:申请正在解决中,通常响应中曾经有局部数据能够用了
  • 4:响应曾经实现,能够获取并应用服务器的响应了
    var xhr = new XMLHttpRequest();
// 0 曾经创立了 ajax 对象 然而还没有对 ajax 对象进行配置
    console.log(xhr.readyState);
    xhr.open('get', 'http://localhost:3000/readystate');
// 1 曾经对 ajax 对象进行配置 然而还没有发送申请
    console.log(xhr.readyState);

// 当 ajax 状态码发生变化的时候登程
    xhr.onreadystatechange = function() {
        // 2 申请曾经发送了
        // 3 曾经接管到服务器端的局部数据了
        // 4 服务器端的响应数据曾经接管实现
        console.log(xhr.readyState);
        // 对 ajax 状态码进行判断 如果状态码的值为 4 就代表数据曾经接管实现了
        if (xhr.readyState == 4) {console.log(xhr.responseText);
        }
    } 

    xhr.send();

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

区别形容 onload 事件 onreadystatechange 事件
是否兼容 IE 低版本 不兼容 兼容
是否须要判断 Ajax 状态码 不须要 须要
被调用次数 一次 屡次

举荐应用 onload 事件

Ajax 错误处理

  1. 网络畅通,服务器端能接管到申请,服务器端返回的后果不是预期后果。

能够判断服务器端返回的状态码,别离进行解决。xhr.status 获取 http 状态码

服务器端设置谬误状态码

res.status(400).send();        // 应用 status()

客服端

// xhr.status 获取 http 状态码
    if(xhr.status == 400) {console.log('申请出错')
    }

2. 网络畅通,服务器端没有接管到申请,返回 404 状态码。

查看申请地址是否谬误。

3. 网络畅通,服务器端能接管到申请,服务器端返回 500 状态码。

服务器端谬误,找后端程序员进行沟通。

4. 网络中断,申请无奈发送到服务器端。

会触发 xhr 对象上面的 onerror 事件,在 onerror 事件处理函数中对谬误进行解决。

// 当网络中断时会触发 onerror 事件
    xhr.onerror = function() {console.log('网络中断,无奈发送申请')
    }

Ajax 状态码:

示意 Ajax 申请的过程状态 ajax 对象返回的

Http 状态码:

示意申请的处理结果 是服务器端返回的

低版本 IE 浏览器的缓存问题

问题:在低版本的 IE 浏览器中,Ajax 申请有重大的缓存问题,即在申请地址不发生变化的状况下,只有第一次申请会真正发送到服务器端,后续的申请都会从浏览器的缓存中获取后果。即便服务器端的数据更新了,客户端仍然拿到的是缓存中的旧数据。

解决方案:在申请地址的前面加申请参数,保障每一次申请中的申请参数的值不雷同。

xhr.open('get', 'http://www.example.com?t=' + Math.random());

服务器端

const fs = require('fs');        // 引入零碎模块,用于读取文件

app.get('/cache', (req, res)=>{fs.readFile('./test.txt', (err, result)=>{res.send(result);
    }) 
})

FormData 对象

FormData 对象的作用

  1. 模仿 HTML 表单,相当于将 HTML 表单映射成表单对象,主动将表单对象中的数据拼接成申请参数的格局
  2. 异步上传二进制文件

<!-- 创立一般的 html 表单 -->
    <form id="form">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="button" id="btn" value="提交">
    </form>

    <script type="text/javascript">
        // 获取按钮
        var btn = document.getElementById('btn');
        // 获取表单
        var form = document.getElementById('form');
        // 为按钮增加点击事件
        btn.onclick = function () {
            
            // 将一般的 html 表单转换为表单对象
            var formData = new FormData(form);
            
            // 创立 ajax 对象
            var xhr = new XMLHttpRequest();
            // 对 ajax 对象进行配置
            xhr.open('post', 'http://localhost:3000/formData');
            
            // 发送 ajax 申请
            xhr.send(formData);
            
            // 监听 xhr 对象上面的 onload 事件
            xhr.onload = function () {
                // 对象 http 状态码进行判断
                if (xhr.status == 200) {console.log(xhr.responseText);
                }
            }
        }
    </script>

服务器端

// 引入 express 框架
const express = require('express');
// 门路解决模块
const path = require('path');
//formidable 表单解析模块
const formidable = require('formidable');
// 创立 web 服务器
const app = express();

// 动态资源拜访服务性能
app.use(express.static(path.join(__dirname, 'public')));

app.post('/formData', (req, res) => {
    // 创立 formidable 表单解析对象
    const form = new formidable.IncomingForm();
    // 解析客户端传递过去的 FormData 对象
    form.parse(req, (err, fields, files) => {res.send(fields);        //fields 解析客户端传递过去的 FormData 对象的数据
    });
});

// 监听端口
app.listen(3000);
// 控制台提醒输入
console.log('服务器启动胜利');

留神:Formdata 对象不能用于 get 申请,因为对象须要被传递到 send 办法中,而 get 申请形式的申请参数只能放在申请地址的前面。服务器端 bodyParser 模块不能解析 formData 对象表单数据,咱们须要应用 formidable 模块进行解析

FormData 对象的实例办法

获取表单对象中属性的值

formData.get('key');

设置表单对象中属性的值


formData.set('key', 'value');
    // 如果设置的表单属性存在 将会笼罩属性原有的值
    // 如果设置的表单属性不存在 将会创立这个表单属性

删除表单对象中属性的值

formData.delete('key');

向表单对象中追加属性值

formData.append('key', 'value');

留神:set 办法与 append 办法的区别是,在属性名已存在的状况下,set 会笼罩已有键名的值,append 会保留两个值。

// 获取表单
var form = document.getElementById('form');
// 将一般的 html 表单转换为表单对象
var formData = new FormData(form);

// 获取表单对象属性的值
    console.log(formData.get('username'));
// 设置的表单属性存在 将会笼罩属性原有的值
    formData.set('username', 'aaa');
    formData.append('username', 'bbb');
// 删除用户输出的明码
    formData.delete('password');

FormData 二进制文件上传

<input type="file" id="file"/>

 var file = document.getElementById('file')
// 当用户抉择文件的时候
 file.onchange = function () {
     // 创立空表单对象
     var formData = new FormData();
     // 将用户抉择的二进制文件追加到表单对象中
     formData.append('attrName', this.files[0]);        //this.files 抉择上传文件的汇合    //attrName 服务器端提供
     // 配置 ajax 对象,申请形式必须为 post
     xhr.open('post', 'www.example.com');
     xhr.send(formData);
 }

服务器端

// 实现文件上传的路由
app.post('/upload', (req, res) => {
    // 创立 formidable 表单解析对象
    const form = new formidable.IncomingForm();
    // 设置客户端上传文件的存储门路
    form.uploadDir = path.join(__dirname, 'public', 'uploads');
    // 保留上传文件的后缀名字
    form.keepExtensions = true;
    // 解析客户端传递过去的 FormData 对象
    form.parse(req, (err, fields, files) => {
        // 将客户端传递过去的文件地址响应到客户端
        res.send({path: files.attrName.path.split('public')[1]
        });
    });
});

FormData 文件上传进度展现

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

Art-template模板引擎

官网地址:https://aui.github.io/art-template/zh-cn/index.html

应用步骤

下载 art-template 模板引擎库文件并在 HTML 页面中引入库文件

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

筹备 art-template 模板

<script id="tpl" type="text/html">
    <div class="box"></div>
</script>

通知模板引擎将哪一个模板和哪个数据进行拼接

var html = template('tpl', {username: 'zhangsan', age: '20'});

将拼接好的 html 字符串增加到页面中

document.getElementById('container').innerHTML = html;

通过模板语法通知模板引擎,数据和 html 字符串要如何拼接

<script id="tpl" type="text/html">
    <div class="box"> {{username}} </div>
</script>

应用 JSONP 解决同源限度问题

jsonp 是 json with padding 的缩写,它不属于 Ajax 申请,但它能够模仿 Ajax 申请

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

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

服务器端

服务器端响应数据必须是一个函数的调用,真正要发送给客户端的数据须要作为函数调用的参数。

const data = 'fn({name:" 张三 ", age:"20"})';
res.send(data);
app.get('/better', (req, res) => {
    // 接管客户端传递过去的函数的名称
    //const fnName = req.query.callback;
    // 将函数名称对应的函数调用代码返回给客户端
    //const data = JSON.stringify({name: "张三"});
    //const result = fnName + '('+ data +')';
    // setTimeout(() => {//     res.send(result);
    // }, 1000)
    res.jsonp({name: 'lisi', age: 20});
});

客户端

在客户端全局作用域下定义函数 fn

在 fn 函数外部对服务器端返回的数据进行解决

function fn (data) { }

function fn (data) {console.log(data); }
<script>
    function fn(data) {console.log("客户端的 fn 函数被调用了");
        console.log(data);
    }
</script>

<!– 1. 将非同源服务器端的申请地址写在 script 标签的 src 属性中 –>

<script src="http://localhost:3001/test"></script>

CORS 跨域资源共享

Node 服务器端设置响应头示例代码

拦挡所有申请
    app.use((req, res, next) => {
    // 1. 容许哪些客户端拜访我
    // * 代表容许所有的客户端拜访我
        res.header('Access-Control-Allow-Origin', '*')
    // 2. 容许客户端应用哪些申请办法拜访我
            res.header('Access-Control-Allow-Methods', 'get,post')
    // 容许客户端发送跨域申请时携带 cookie 信息
        res.header('Access-Control-Allow-Credentials', true);
        next();});

withCredentials 属性

在应用 Ajax 技术发送跨域申请时,默认状况下不会在申请中携带 cookie 信息。

withCredentials:指定在波及到跨域申请时,是否携带 cookie 信息,默认值为 false

Access-Control-Allow-Credentials:true 容许客户端发送申请时携带 cookie

正文完
 0