美文网首页
Ajax笔记

Ajax笔记

作者: Scincyc | 来源:发表于2020-08-21 22:41 被阅读0次

1. Ajax 基础

1.1 传统网站中存在的问题

  • 网速慢的情况下,页面加载时间长,用户只能等待

  • 表单提交后,如果一项内容不合格,需要重新填写所有表单内容

  • 页面跳转,重新加载页面,造成资源浪费,增加用户等待时间

1.2 Ajax 概述

Ajax:标准读音 [ˈeɪˌdʒæks] ,中文音译:阿贾克斯

它是浏览器提供的一套方法,可以实现页面无刷新更新数据,提高用户浏览网站应用的体验

1.3 Ajax 的应用场景

  • 页面上拉加载更多数据
  • 列表数据无刷新分页
  • 表单项离开焦点数据验证
  • 搜索框提示文字下拉列表

1.4 Ajax 的运行环境

Ajax 技术需要运行在网站环境中才能生效,当前课程会使用Node创建的服务器作为网站服务器

2. Ajax 运行原理及实现

2.1 Ajax 运行原理

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

2.2 Ajax 的实现步骤

//1. 创建 Ajax 对象
var xhr = new XMLHttpRequest();
//2.  告诉 Ajax 请求后端的地址以及请求方式
 xhr.open('get', 'http://www.example.com');
//3.  发送请求
 xhr.send();
//4.  获取服务器端给与客户端的响应数据
 xhr.onload = function () {
     console.log(xhr.responseText);
 }

2.3 服务器端响应的数据格式

在真实的项目中,服务器端大多数情况下会以 JSON 对象作为响应数据的格式。当客户端拿到响应数据时,会被转换为对象字符串,所以要将 对象字符串转换为JSON 数据,再和 HTML 字符串进行拼接,然后将拼接的结果展示在页面中

注意:在 http 请求与响应的过程中,无论是请求参数还是响应内容,如果是对象类型,最终都会被转换为对象字符串进行传输

 JSON.parse() // 将 json 字符串转换为json对象
JSON.stringify() // 将json对象转换为json字符串

get start

//客户端html文件
<script type="text/javascript">
        // 1.创建ajax对象
        var xhr = new XMLHttpRequest();
        // 2.告诉Ajax对象要向哪发送请求,以什么方式发送请求
        // 1)请求方式 2)请求地址
        xhr.open('get', 'http://localhost:3000/responseData');
        // 3.发送请求
        xhr.send();
        // 4.获取服务器端响应到客户端的数据
        xhr.onload = function (){
            // console.log(typeof xhr.responseText)
            // 将JSON字符串转换为JSON对象
            var responseText = JSON.parse(xhr.responseText);
            // 测试:在控制台输出处理结果
            console.log(responseText,responseText.name)
        }
</script>
// 服务器端app.js

// 引入express框架
const express = require('express');
// 路径处理模块
const path = require('path');
// 创建web服务器
const app = express();
// 静态资源访问服务功能
app.use(express.static(path.join(__dirname, 'public')));
// 返回响应
app.get('/responseData', (req, res) => {
    res.send({"name": "zs"});
});

2.4 请求参数传递

传统网站表单提交

 <form method="get" action="http://www.example.com">
     <input type="text" name="username"/>
     <input type="password" name="password">
 </form>
 <!–- http://www.example.com?username=zhangsan&password=123456 -->

2.4.1 GET 请求方式

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

get start

//1. 客户端文件

var xhr = new XMLHttpRequest();
// get方式
var params = 'name=zhangsan&age=20';
xhr.open('get', 'http://www.example.com?'+params);
xhr.send();
// 获取服务器端响应到客户端
xhr.onload = function (){
    var responseText = JSON.parse(xhr.responseText);
    console.log(responseText);
}
//结果:{name: zhangsan, age: 20}
//2. 服务器端app.js

const express = require('express');
const path = require('path');
// 创建web服务器
const app = express();
// 静态资源访问服务功能
app.use(express.static(path.join(__dirname, 'public')));
// 返回响应
app.get('/get', (req, res) => {
    res.send(req.query);
});

2.4.2 POST 请求方式

xhr.open('post', 'http://localhost:3000/post');
//设置报文头(post请求必须要设置)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//设置报文体
xhr.send('name=zhangsan&age=20');

请求参数的格式:

  1. application/x-www-form-urlencoded

    name=zhangsan&age=20&sex=男
    
  2. application/json

     {name: 'zhangsan', age: '20', sex: '男'}
    

    在请求头中指定 Content-Type 属性的值是 application/json,告诉服务器端当前请求参数的格式是 json

     JSON.stringify() // 将json对象转换为json字符串
    

注意:get 请求是不能提交 json 对象数据格式的,传统网站的表单提交也是不支持 json 对象数据格式的

get start

  • application/x-www-form-urlencoded格式参数 服务端的处理
//1. 客户端文件
var xhr = new XMLHttpRequest();
xhr.open('post', 'http://localhost:3000/post');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('name=zhangsan&age=20');
// 获取服务器端响应的数据
xhr.onload = function () {
    var responseText = JSON.parse(xhr.responseText);
    console.log(responseText);
}
//结果:{name: zhangsan, age: 20}
//2. 服务器端app.js

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
//服务端配置具体的格式
app.use(bodyParser.urlencoded());

const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.post('/post', (req, res) => {
    // 需要引入body-parser模块
    res.send(req.body);
});
  • 客户端application/json 格式参数 服务端的处理
//1.客户端
var xhr = new XMLHttpRequest();
xhr.open('post', 'http://localhost:3000/json');
xhr.setRequestHeader('Content-Type', 'application/json');
// JSON.stringify() 将json对象转换为json字符串
// 3.发送请求 (参数必须为字符串)
xhr.send(JSON.stringify({name: 'lisi', age:50}));
xhr.onload = function (){
    console.log(xhr.responseText)
}
//结果:{"name":"lisi","age":50}
//2. 服务器端app.js

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
//服务端配置具体的格式
app.use(bodyParser.json());

const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.post('/post', (req, res) => {
    // 需要引入body-parser模块
    res.send(req.body);
});

2.5 获取服务器端的响应

2.5.1 Ajax 状态码

在创建ajax对象,配置ajax对象,发送请求,以及接收完服务器端响应数据,这个过程中的每一个步骤都会对应一个数值,这个数值就是ajax状态码

0:请求未初始化(还没有调用open())
1:请求已经建立,但是还没有发送(还没有调用send())
2:请求已经发送
3:请求正在处理中,通常响应中已经有部分数据可以用了
4:响应已经完成,可以获取并使用服务器的响应了

 xhr.readyState // 获取Ajax状态码

2.5.2 onreadystatechange 事件

当 Ajax 状态码发生变化时将自动触发该事件

在事件处理函数中可以获取 Ajax 状态码并对其进行判断,当状态码为 4 时就可以通过 xhr.responseText 获取服务器端的响应数据了

 // 当Ajax状态码发生变化时
 xhr.onreadystatechange = function () {
     // 判断当Ajax状态码为4时
     if (xhr.readyState == 4) {
         // 获取服务器端的响应数据
         console.log(xhr.responseText);
     }
 }

get start

// 1.客户端
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();
//0 1 2 3 4 hello
//2. 服务器端app.js
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.get('/get', (req, res) => {
    res.send('hello');
});

2.5.3 获取服务器端的响应

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

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

2.6 Ajax 错误处理

  1. 网络畅通,服务器端能接收到请求,服务器端返回的结果不是预期结果。
    可以判断服务器端返回的状态码,分别进行处理。xhr.status 获取http状态码

  2. 网络畅通,服务器端没有接收到请求,返回404状态码。
    检查请求地址是否错误

  3. 网络畅通,服务器端能接收到请求,服务器端返回500状态码。
    服务器端错误,找后端程序员进行沟通

  4. 网络中断,请求无法发送到服务器端。
    会触发xhr对象下面的onerror事件,在onerror事件处理函数中对错误进行处理

get start

var btn = document.getElementById('btn');

btn.onclick = function () {
    // 1.创建ajax对象
    var xhr = new XMLHttpRequest();
    // 2.告诉Ajax对象要向哪发送请求,以什么方式发送请求
    // 1)请求方式 2)请求地址
    xhr.open('get', 'http://localhost:3000/error');//请求地址错误404
    // 3.发送请求
    xhr.send();
    // 4.获取服务器端响应到客户端的数据
    xhr.onload = function (){
        // xhr.status 获取http状态码
        console.log(xhr.responseText);

        if (xhr.status == 400) {
            alert('请求出错')
        }
    }
    // 当网络中断时会触发onerrr事件
    xhr.onerror = function () {
        alert('网络中断, 无法发送Ajax请求')
    }
}

// Ajax状态码: 表示Ajax请求的过程状态 ajax对象返回的
// Http状态码: 表示请求的处理结果 是服务器端返回的
//服务器端
...
app.get('/error', (req, res) => {
    //console.log(abc);语法错误500
    res.status(400).send('not ok');
});

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

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

解决方案:在请求地址的后面加请求参数,保证每一次请求的请求参数的值不相同

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

get start

var btn = document.getElementById('btn');

btn.onclick = function () {
    var xhr = new XMLHttpRequest();
    // 请求参数的值不相同
    xhr.open('get', 'http://localhost:3000/cache?t=' + Math.random());
    xhr.send();
    
    xhr.onreadystatechange = function (){
        // 数据已经接收完成并响应正常
        if (xhr.readyState == 4 && xhr.status == 200) {
            alert(xhr.responseText);
        }
    }
}
const fs = require('fs');
...
app.get('/cache', (req, res) => {
    fs.readFile('./test.txt', (err, result) => {
        res.send(result);
    });
});

3. Ajax 异步编程

3.1 同步异步概述

3.1.1 同步

上一行代码执行完成后,才能执行下一行代码,即代码逐行执行

3.1.2 异步

异步代码虽然需要花费时间去执行,但程序不会等待异步代码执行完成后再继续执行后续代码,而是直接执行后续代码,当后续代码执行完成后再回头看异步代码是否返回结果,如果已有返回结果,再调用事先准备好的回调函数处理异步代码执行的结果

 console.log('before');
 setTimeout(
    () => { console.log('last');
 }, 2000);
 console.log('after');

3.2 Ajax 封装

问题:发送一次请求代码过多,发送多次请求代码冗余且重复

解决方案:将请求代码封装到函数中,发请求时调用函数即可

 ajax({ 
     type: 'get',
     url: 'http://www.example.com',
     success: function (data) { 
         console.log(data);
     }
 })

请求参数要考虑的问题

1.请求参数位置的问题

将请求参数传递到ajax函数内部, 在函数内部根据请求方式的不同将请求参数放置在不同的位置

  • get 放在请求地址的后面
  • post 放在send方法中

2.请求参数格式的问题

  • application/x-www-form-urlencoded

         参数名称=参数值&参数名称=参数值
    

​ name=zhangsan&age=20

  • application/json

​ {name: 'zhangsan', age: 20}

​ 1).传递对象数据类型对于函数的调用者更加友好

​ 2).在函数内部对象数据类型转换为字符串数据类型更加方便

// ajax函数的封装
function ajax(options) {
    // 默认参数
    var defaults = {
        type: 'get',
        url: '',
        data: {},
        header: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        success: function () { },
        error: function () { }
    }
    // 使用defaults的属性覆盖options的属性
    Object.assign(defaults, options);

    // 参数的格式转换
    var params = '';
    for (var attr in defaults.data) {
        params += attr + '=' + defaults.data[attr] + '&';
    }
    // 最后一个&字符截去
    params = params.substr(0, params.length - 1);
    console.log(params);



    var xhr = new XMLHttpRequest();

    // 请求类型不同 参数位置不同
    if (defaults.type == 'get') {
        xhr.open(defaults.type, defaults.url + '?' + params);
        xhr.send();
    } else if (defaults.type == 'post') {
        // 用户传递的参数类型
        var contentType = defaults.header['Content-Type'];
        xhr.open(defaults.type, defaults.url);
        xhr.setRequestHeader('Content-Type', contentType)
        // 请求参数类型不同
        if (contentType == 'application/json') {
            xhr.send(JSON.stringify(defaults.data));
        } else {
            xhr.send(params);
        }
    }

    // 响应处理函数
    xhr.onload = function () {
        // 服务器端的响应类型
        var contentType = xhr.getResponseHeader('Content-Type');
        // 将返回的对象字符串转换为对象
        var responseText = xhr.responseText;
        console.log('contentType', contentType);
        if (contentType.includes('application/json')) {
            responseText = JSON.parse(responseText);
        }

        if (xhr.status == 200) {
            options.success(responseText);
        } else {
            options.error(responseText);
        }
    }
}
// 配置ajax函数的参数
ajax({
    type: 'get',
    url: 'http://localhost:3000/responseData',
    data: {
        name: 'zhangsan',
        age: 18
    },
    header: {
        'Content-Type': 'application/json'
    },
    success: function (data) {
        console.log(data + '获取成功');
    },
    error: function (data) {
        console.log(data + '获取失败');
    }
});
//输出:
//name=zhangsan&age=18
//contentType application/json; charset=utf-8
//[object Object]获取成功
...
app.get('/responseData', (req, res) => {
    res.send({"name": "zs"});
});

4. FormData

4.1 FormData对象的作用

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

4.2 FormData对象的使用

<!-- 1.创建表单对象 -->
    <form id="form">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="text" id="btn" value="提交"> 
    </form>
    <script>
        //2. 获取表单对象
        var form = document.getElementById('form');
        var btn = document.getElementById('btn');
        btn.onclick = function() {
            // 3.将 HTML 表单转化为 formData 对象
            var param = new FormData(form);
            var xhr = new XMLHttpRequest();
            xhr.open('post', 'http://localhost:3000/formData');
            // 4.提交表单对象 到服务器端(post)
            xhr.send(param);
        }
        // 5.监听xhr对象下面的onload,接收响应数据
        xhr.onload = function() {
            if(xhr.status == 200) {
                // 响应正常
                console.log(xhr.responseText);
            }
        }
        // 6.异常处理
        xhr.onerror = function() {
            console.log("响应异常");
        }

    </script>

  • 注意:
  • Formdata 对象不能用于 get 请求,因为对象需要被传递到 send 方法中,而 get 请求方式的请求参数只能放在请求地址的后面。
  • 服务器端 bodyParser 模块不能解析 formData 对象表单数据,我们需要使用 formidable 模块进行解析。

4.2 formidable模块

  • 之前一直使用body-parse模块对客户端post传递的参数进行解析
  • 但是body-parse模块不能对FormData进行解析
  • 需要下载和使用另一个模块formidable
// 服务器端app.js
const formidable = require('formidable');
// 创建网站服务器...引入http模块
...
// 处理formData路由请求
app.post('/formData', (res, req) => {
    // 创建formidable表单解析对象
    const form = new formidable.IncomingForm();
    // 解析客户端传过来的FormData对象 参数:错误对象 普通参数组成的对象 上传文件
    form.parse(req, (err, fields, files) => {
        res.send(fields);
    })
});

// 监听端口
app.listen(3000);
console.log("服务器响应成功");

4.3 实例方法

// 1.获取表单对象的属性的值
formData.get('key');

// 2.设置表单对象属性的值
formData.set('key', 'value');
// 注意:如果设置的key不存在,将会创建这个表单属性
// 注意:如果设置的key存在,将会改变这个表单属性的值

// 3.删除表单对象的属性
formData.delete('key');

// 4.向表单对象追加一个
formData.append('key', 'value');
var f = new FormData();//创建空的表单对象
f.append('sex','nan');
console.log(f.get('sex'));
  • 注意:set和append方法的区别:当属性存在时,set会改变属性的值,而append会保留2个属性及其值,但是服务器只会接收属性最后传递的值

4.4 FormData二进制文件上传

  • get请求方式不能用于文件上传
<input type="file" id="file">
<script>
    var file = document.getElementById('file');
    // 当用户选择文件的时候
    file.onchange = function(){
        var formData = new FormData();
        // 将用户选择的二进制文件追加到表单对象中
        formData.append('attrName', this.files[0]);
        // 创建ajax对象
        var xhr = new XMLHttpRequest();
        // 初始化ajax对象,请求方式必须为post
        xhr.open('post', 'http://localhost:3000/upload');
        xhr.send(formData);
        // 监听响应数据
        xhr.onload = function() {
            if(xhr.status == 200) {
                // 请求成功 响应正常
                console.log(xhr.responseText);
            }
        }

    }
</script>
// 服务器端
app.post('/upload', (req, res) => {
            // 创建解析对象
            const form = new formidable.IncomingForm();
            // 设置客户端上传文件的存储路径 __dirname找到当前目录,拼接后面的路径
            form.uploadDir = path.join(__dirname, 'public','uploads');
            // 保存文件后缀
            form.keepExtensions = true;
            // 解析客户端请求参数
            form.parse(req, (err, fields, files) => {
                res.send("ok");
            });
        })

文件上传进度展示

<div class = "progress">
    <div class = "progress-bar" id="bar" style="width:60%">60%</div>
</div>
var bar = document.getElementById('bar');
file.change = function() {
    // xhr的upload保存了文件上传的相关信息
    // 在文件上传过程 会持续触发onprogress事件(参数:事件对象)
    xhr.upload.onprogress = function(event) {
        // 文件上传了多少loaded
        // 文件总大小total
        var result = (event.loaded / event/total) * 100 + '%';
        // 将结果赋值给进度条的宽度属性
        bar.style.width = result;
        bar.innerHTML = result;
    }
}

上传图片即时预览

  • 在服务器端中,将客户端上传的图片地址响应到客户端,显示出来
  • 由于图片是静态资源,可以直接访问,需要spilt分割路径
    form.parse(req, (err, fields, files) => {
        // attrName是客户端传过来的FormData对象的属性名
        res.send({
            path: files.attrName.path.split('public')[1]
        });
        // 此时得到的是/uploads/...jpg
    })
<div id="box"></div>
<script>
    var box = document.getElementById('box');
    xhr.onload = function() {
        if(xhr.status == 200) {
            var result = JSON.parse(xhr.responseText);
            // 动态创建img元素,不想让用户看到图片加载的过程
            var img = document.createElement('img');
            img.src = result.path;
            // 当图片加载完之后,显示到页面中
            // img上有onload事件 加载图片完触发
            img.onload = function() {
                box.appendChild(img);
            }
        }
    }
</script>

5. Ajax请求限制-同源政策

5.1 Ajax请求限制

  • Ajax只能向自己的服务器发送请求
  • 不能向其他网站的服务器发送请求

什么是同源?

  • 多个请求/页面是否来自同一个服务器端
  • 判断的标准:三个都相同(协议 域名 端口),否则不同源
  • 不写端口,默认80

同源政策的目的

  • 同源政策是为了保护用户的信息安全,防止恶意的网站窃取数据
  • 最初的同源政策是指A网站在客户端设置的Cookie,B网站不能访问
  • 非同源的网站之间是不能发送ajax请求的
  • 如果发送了,请求是可以发送出去的,只不过浏览器拒绝接收服务器端的响应,所以请求报错

5.2 解决同源限制问题-使用JSONP

jsonp是json with padding的缩写,可以模拟ajax请求,但不是ajax请求

原理:利用script标签可以向非同源的服务器端发送请求的特性, 在服务端中返回函数调用的代码,(虽然服务端返回的是字符串,但因为写在客户端script中,会被当做js执行)当客户端加载完响应内容以后,这段响应内容会被当做js来执行,函数就被调用了,此时客户端已经提前准备好了函数的定义,通过函数的参数就可以获取接收的数据

(1)不同源的服务器端请求地址写在script标签的src属性中

<script src="www.example.com"></script>
<script src=“https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

(2)服务端返回的是函数调用语句的字符串,(不是字符串就会直接在服务端执行,而实际我们想在客户端执行),同时发送给客户端的数据作为函数调用的参数传递

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

(3)在客户端全局下定义好函数fn(以便返回的函数调用语句执行时不会说函数不存在)

 function fn (data) { }

(4)在 fn 函数内部对服务器端返回的数据进行处理

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

例子:

<!-- 1号网站http://localhost:3000 客户端 -->
  <script>
      function fn(data) {
          console.log('客户端的fn被调用了');
          console.log(data);
      }
  </script>
    <!-- 在下面服务器地址加载完毕后 会调用上面的函数 -->
  <script src="http://localhost:3001/test"></script>

// 2号网站http://localhost:3001 服务端
app.get('test', (req, res) => {
    const result = 'fn({name: "ccc"})';
    res.send(result);
})

JSON代码优化

  • script在html页面中会自动加载,需要将script请求的发送变为动态请求
  • 客户端需要将函数的名称传递到服务器端
  • 封装jsonp函数,方便请求发送
  • 服务器端代码优化之 res.jsonp 方法
<button id='btn'></button>
var btn = document.createElement('script');
script.src = 'http://localhost:3001/test';
document.body.appendChild(script);
// script标签加载完时触发
script.onload = function () {
    // 加载完 script标签就没有意义了
    document.body.removeChild(script);
}
  • 客户端将更新后的函数的名称传递到服务器端,需要在请求地址后,通过get方式添加callback参数,参数的值就是函数名称
script.src = 'http://localhost:3001/test?callback=fn';
// 2号网站http://localhost:3001 服务端
app.get('test', (req, res) => {
    const fnName = req.query.callback;
    // 将函数名称对应的函数调用代码返回客户端
    const result = fnName + '({name: "ccc"})';
    res.send(result);
    // 服务端以上代码优化 等价于下面一句
    // res.jsonp({name:"ccc"});
})
  • 封装jsonp函数,参数为对象,包含请求地址url属性(添加callback参数)
综合上面代码进行封装:
1.动态创建script标签,添加src属性为url

2.绑定加载事件onload,删除加载完无意义的当前script

完整的代码优化过程

  • btn点击事件中,调用jsonp({url})函数

  • 服务端中获取req.query.callback函数名称

  • 在返回函数调用代码中,添加函数名

  • 函数定义添加到jsonp对象参数中

  • get请求参数添加到jsonp对象参数中

5.3 CORS 跨域资源共享

CORS:全称为 Cross-origin resource sharing,即跨域资源共享,它允许浏览器向跨域服务器发送 Ajax 请求,克服了 Ajax 只能同源使用的限制

浏览器向服务端发送请求,请求头 (origin)

服务端向客户端返回响应,响应头(Access-Control-Access-Origin)

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

     app.use((req, res, next) => {
         res.header('Access-Control-Allow-Origin', '*');
         res.header('Access-Control-Allow-Methods', 'GET, POST');
         next();
     })
    

5.4 同源政策-服务端解决方案

服务端不存在同源政策

  • 使用到第三方模块request
  • 客户端先向自身的服务端发送请求
  • 用自身的服务器端利用request(url, (err, res, body) = {})向其他服务器端发送请求

6. withCredentials属性

  • http协议的无状态:客户端和服务器端之间的请求和响应遵循http协议的无状态,也就是谁也不认识谁,只要有请求发送,服务端就响应,但服务端并不知道客户端已经来过一次
  • cookie:客户端第一次访问服务器端时,服务器端会向客户端发送一个响应cookie,这是服务端对客户端的唯一识别,有利于服务端和客户端之间的持久连接。当客户端再次发送请求时,cookie会随着请求发送到服务端,用于识别身份
  • 但是,在使用ajax发送跨域请求时,默认不会在请求中携带cookie信息
  • 如果想要在跨域请求中携带cookie,需要在服务器端和客户端都设置Credentials
// 1.在网站1客户端中设置
// 当发送跨域请求时,携带cookie信息
xhr.wiithCredentials = true; 
xhr.send(formData);

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

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

// 2.在网站2服务端中设置
// 允许客户端发送跨域请求时携带cookie信息
res.header('Access-Control-Allow-Credentials', true);
// 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
// 2.允许客户端使用哪些请求方法访问我
res.header('Access-Control-Allow-Methods', 'get,post')

7. $.ajax()

7.1 $.ajax()方法概述

7.1.1 作用:发送Ajax请求

 $.ajax({
     type: 'get',
     url: 'http://www.example.com',
     data: { name: 'zhangsan', age: '20' },
     contentType: 'application/x-www-form-urlencoded',
     beforeSend: function () { 
         return false
     },
     success: function (response) {},
     error: function (xhr) {}
});

 {
     data: 'name=zhangsan&age=20'
 }
 {
     contentType: 'application/json'
 }
JSON.stringify({name: 'zhangsan', age: '20'})

7.1.2 作用:发送jsonp请求

$.ajax({
    url: 'http://www.example.com',
    // 指定当前发送jsonp请求
    dataType: 'jsonp',
    // 修改callback参数名称,默认叫callback
    jsonp: 'cb',
    // 指定函数名称
    jsonCallback: 'fnName',
    success: function (response) {} 
})

7.2 serialize方法

作用:将表单中的数据自动拼接成字符串类型的参数

var params = $('#form').serialize();
// name=zhangsan&age=30

7.3 .get()、.post()

作用:.get方法用于发送get请求,.post方法用于发送post请求

$.get('http://www.example.com', {name: 'zhangsan', age: 30}, function (response) {}) 
$.post('http://www.example.com', {name: 'lisi', age: 22}, function (response) {})

三个参数:请求地址,请求参数,请求成功时回调函数(请求参数可省略)

8. jQuery中Ajax全局事件

8.1 全局事件

只要页面中有Ajax请求被发送,对应的全局事件就会被触发

全局事件必须被绑定在document元素上

.ajaxStart()     // 当请求开始发送时触发
.ajaxComplete()  // 当请求完成时触发
$(document).on('ajaxStart', function() {})

8.2 NProgress

官宣:纳米级进度条,使用逼真的涓流动画来告诉用户正在发生的事情!

<link rel='stylesheet' href='nprogress.css'/>
<script src='nprogress.js'></script>
NProgress.start();  // 进度条开始运动 
NProgress.done();   // 进度条结束运动
$(document).on('ajaxStart', function() {
    NProgress.start();
})

9. RESTful 风格的 API

9.1 传统请求地址

GET http://www.example.com/getUsers         // 获取用户列表
GET http://www.example.com/getUser?id=1     // 比如获取某一个用户的信息
POST http://www.example.com/modifyUser      // 修改用户信息
GET http://www.example.com/deleteUser?id=1  // 删除用户信息

9.2 RESTful API 概述

一套关于设计请求的规范

GET:      获取数据
POST:    添加数据
PUT:      更新数据
DELETE: 删除数据
请求数据 => 请求地址
users => /users
articles => /articles 

RESTful API 的实现:

GET:http://www.example.com/users 获取用户列表数据
POST:http://www.example.com/users 创建(添加)用户数据
GET:http://www.example.com/users/1 获取用户ID为1的用户信息
PUT:http://www.example.com/users/1 修改用户ID为1的用户信息
DELETE:http://www.example.com/users/1 删除用户ID为1的用户信息
// 服务器端
app.put('/users/:id', (req, res) => {
    const id = req.params.id;
    res.send(`当前我们在修改id为${id}的用户信息`);
})
//客户端
$.ajax({
    type: 'put',
    url: '/users/10',
    success: function(response) {
        console.log(response);
    }
})

10. XML

XML 的全称是 extensible markup language,代表可扩展标记语言,它的作用是传输和存储数据

 <students> 
     <student>
         <sid>001</sid>
         <name>张三</name>
         </student>
     <student>
         <sid>002</sid>
         <name>王二丫</name>
         </student>
 </students>

XML DOM

XML DOM 即 XML 文档对象模型,是 w3c 组织定义的一套操作 XML 文档对象的API。浏览器会将 XML 文档解析成文档对象模型

//客户端
xhr.onload = function () {
    // xhr.responseXML 获取服务器端返回的xml数据
    var xmlDocument = xhr.responseXML;
    var title = xmlDocument.getElementsByTagName('title')[0].innerHTML;
    container.innerHTML = title;
}
// 服务器端
app.get('/xml', (req, res) => {
    res.header('content-type', 'text/xml');
    res.send('<message><title>消息标题</title><content>消息内容</content></message>')
});

相关文章

  • ajax学习笔记

    Ajax学习笔记 Ajax简介 1. Ajax是什么? Ajax : Asynochronous javascri...

  • 2018-06-01

    # Ajax标签(空格分隔): 笔记整理---[TOC]### 从输入网址开始:- 在学习ajax之前,你应该先了...

  • ajax请求 有时会有状态码0

    资料 【error】jQuery ajax请求错误返回status 0和错误error的问题 【开发笔记】ajax...

  • ajax笔记

    XMLHttpRequest对象 1.onreadystatechange 2.readyState 属性0:请求...

  • Ajax笔记

    什么事Ajax? AJAX是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下 创建步骤 创建一个...

  • Ajax笔记

    Ajax(Asynchronous JavaScript and XML ): JavaScript通过异步的方式...

  • Ajax 笔记

    Ajax 使用 创建动态网页的技术 Ajax 介绍 AJAX = Asynchronous JavaScript ...

  • Ajax笔记

    AJAX简单介绍 AJAX = Asynchronous JavaScript and XML(异步的 JavaS...

  • Ajax笔记

    XMLHttpRequest的出现使得网页客户端和服务器异步传输数据成为可能。

  • Ajax笔记

    一,1个HTTP请求一般由四部分组成: (1)GET请求:一般用于信息获取a.使用URL传递参数b.对所发送信息的...

网友评论

      本文标题:Ajax笔记

      本文链接:https://www.haomeiwen.com/subject/mmxmjktx.html