Ajax_$.ajax_模版引擎_FormData_同源政策(jsonp) formData serialize方法

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

实现步骤:

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);
 }

数据格式

http://www.example.com?name=zhang&age=18

一般:服务器端会以 JSON 对象作为响应数据的格式。当客户端拿到响应数据时,要将 JSON 数据和 HTML 字符串进行拼接,然后将拼接的结果展示在页面中。(模版引擎)

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

所以需要用到

JSON.parse() // 将 json 字符串转换为json对象--一般用在接受响应数据
JSON.stringify() // 将json对象转换为json字符串--一般用在post请求 且数据格式设为json模式时

 

POST请求


var xhr = new XMLHttpRequest();
//post请求 地址内不能放参数数据
xhr.open('post', 'http://www.example.com');
//设置请求参数的格式  还有application/json格式
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
//post请求将请求参数放入send()方法内
xhr.send('name=zhangsan&age=20');
xhr.onload = function () {
     console.log(xhr.responseText);
 }
若是json格式 需将请求参数设置为json字符串JSON.stringify()

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

 

 

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

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

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

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

 

扩展补充

模版引擎

  1. 下载 art-template 并引入
  2. 准备好模版
  3. 说明与哪个数据拼接 template('tpl', {info:data});
  4. 将拼接好的html字符串添加到页面中

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

FormData

FormData对象的作用

1.模拟HTML表单,相当于将HTML表单映射成表单对象,自动将表单对象中的数据拼接成请求参数的格式

2.异步上传二进制文件

 

FormData对象的使用

1.准备 HTML 表单 <form id="form">...</form>

2. 将 HTML 表单转化为 formData 对象

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

3.提交表单对象

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

 

FormData 对象的实例方法

1.获取表单对象中属性的值  

formData.get('key');

2.设置表单对象中属性的值

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

3.删除表单对象中属性的值

 formData.delete('key');

4. 向表单对象中追加属性值

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


注意:set 方法与 append 方法的区别是,在属性名已存在的情况下,set 会覆盖已有键名的值,append会保留两个值。

 

FormData 二进制文件上传

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

FormData 文件上传进度展示

文件上传过程中持续触发onprogress事件

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

 

FormData 文件上传图片即时预览

图片上传到服务器端以后,服务器端通常都会将图片地址做为响应数据传递到客户端,客户端可以从响应数据中获取图片地址,然后将图片再显示在页面中。

xhr.onload = function () {
//将响应的数据转化为json对象
     var result = JSON.parse(xhr.responseText);
//创建img元素
     var img = document.createElement('img');
//将响应的地址数据赋值给预览图片
     img.src = result.src;
//img元素加载完后添加到boby内
     img.onload = function () {
         document.body.appendChild(this);
     }
 }

 

同源政策

Ajax 只能向自己的服务器发送请求。比如现在有一个A网站、有一个B网站,A网站中的 HTML 文件只能向A网站服务器中发送 Ajax 请求,B网站中的 HTML 文件只能向 B 网站中发送 Ajax 请求,但是 A 网站是不能向 B 网站发送 Ajax请求的,同理,B 网站也不能向 A 网站发送 Ajax请求。

 

 什么是同源

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

https://www.example.com:80/dir/page.html

 

解决同源政策限制

一.使用 JSONP 

    jsonp 是 json with padding 的缩写,它不属于 Ajax 请求,但它可以模拟 Ajax 请求。(使用script标签)  

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

 

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

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

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

function fn(data){
//需要获取的数据data
console.log(data)
}

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

 

JSONP代码优化

  1. 客户端需要将函数名称传递到服务器端。

  2. 将 script 请求的发送变成动态请求。

  3. 封装 jsonp 函数,方便请求发送。

  4. 服务器端代码优化之 res.jsonp 方法。

//jsonp封装函数 当然jquery已经封装功能更全更强大的jsonp方法和ajax方法 直接使用即可$.ajax()
function jsonp (options) {
    // 动态创建script标签
    var script = document.createElement('script');
    // 拼接字符串的变量
    var params = '';

    for (var attr in options.data) {
        params += '&' + attr + '=' + options.data[attr];
    }
    // myJsonp0124741
    var fnName = 'myJsonp' + Math.random().toString().replace('.', '');
    // 它已经不是一个全局函数了
    // 我们要想办法将它变成全局函数
    window[fnName] = options.success;
    // 为script标签添加src属性
    script.src = options.url + '?callback=' + fnName + params;
    // 将script标签追加到页面中
    document.body.appendChild(script);
    // 为script标签添加onload事件
    script.onload = function () {
        document.body.removeChild(script);
    }
}

 

 

二.CORS 跨域资源共享

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

 

Node 服务器端设置响应头:

 app.use((req, res, next) => {
//允许访问的地址域 *代表所有 也可指定地址域 如:Access-Control-Allow-Origin: 'http://localhost:3000'
     res.header('Access-Control-Allow-Origin', '*');
//设置允许访问的请求方式 'GET', 'POST' 或者两者都可
     res.header('Access-Control-Allow-Methods', 'GET, POST');
     next();
 })

 

三 服务器端之间访问

同源政策是浏览器给予Ajax技术的限制,服务器端是不存在同源政策限制

可以服务器之间先访问      需要在服务器端用到require('request')模块

得到的数据 再通过ajax发送给客服端

 

cookie与跨域请求

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

 

withCredentials属性: 

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

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

  

 比如实现跨域登陆:  在网站A中客户端发起请求 

loginBtn.onclick = function () {
            // 将html表单转换为formData表单对象
            var formData = new FormData(loginForm);
            // 创建ajax对象
            var xhr = new XMLHttpRequest();
            // 对ajax对象进行配置
            xhr.open('post', 'http://localhost:3001/login');
            // 当发送跨域请求时,设置携带cookie信息(重点)
            xhr.withCredentials = true;
            // 发送请求并传递请求参数
            xhr.send(formData);
            // 监听服务器端给予的响应内容
            xhr.onload = function () {
                console.log(xhr.responseText);
            }
        }

B网站服务端:

// 拦截所有请求
app.use((req, res, next) => {
    // 1.允许哪些客户端访问我
    // * 代表允许所有的客户端访问我
    // 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
    // 2.允许客户端使用哪些请求方法访问我
    res.header('Access-Control-Allow-Methods', 'get,post')
    // 允许客户端发送跨域请求时携带cookie信息
    res.header('Access-Control-Allow-Credentials', true);
    next();
});

 

 

jQuery 中的 Ajax

作用:发送Ajax请求。

 $.ajax({
     type: 'get',
     url: 'http://www.example.com',
     data: { name: 'zhangsan', age: '20' },
//若是get请求可以省去 contentType属性
     contentType: 'application/x-www-form-urlencoded',
//请求发送前执行
     beforeSend: function () { 
         return false
     },
     success: function (response) {},
     error: function (xhr) {}
});

 

作用:发送jsonp请求

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

$.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) {})

 

serialize方法:

formData可以拼接表单参数  但 formData为H5 有兼容性
serializa()方法 可以拼接 但只能拼接 没有其他功能 可以自己利用serializaArry() 方法封装一个转化为对象的函数

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

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

 

全局事件

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

.ajaxStart() // 当请求开始发送时触发

.ajaxComplete() // 当请求完成时触发

//当页面有ajax请求发送时触发
$(document).on('ajaxStart', function () {
NProgress.start()
) //当页面有ajax请求完成时触发 
$(document).on('ajaxComplate', function () {
NProgress.done()
)

 

NProgress  纳米级进度条

 使用: 引入 相关的 css文件 与 js文件

             2 在代码开始写入

<script>NProgress.start()</script>

    和在代码结尾处

<script>NProgress.done()</script>

 

 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

location.href= 'index.html'  //跳转地址    
location.reload()   //刷新当前页面 
llocation.search()   //获取到当前地址参数 类似 ?name=zhangsan&age=18

//自己封装一个获取地址栏内的指定参数 没有则返回 -1

function getUrlParams(name) {
    var paramsAry = location.search.substr(1).split('&');
    // 循环数据
    for (var i = 0; i < paramsAry.length; i++) {
        var tmp = paramsAry[i].split('=');
        if (tmp[0] == name) {
            return tmp[1];
        }
    }
    return -1;
}

 

posted @ 2021-02-26 14:41  勿扰。。清梦  阅读(166)  评论(0)    收藏  举报