FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。
其主要用于发送表单数据,但亦可用于发送带键数据(key data),而独立于表单使用。
如果表单enctype属性设为multipart/form-data ,则会使用表单的submit()方法来发送数据,从而,发送数据具有同样形式。key是唯一的,一个key可能对应多个value。
如果是使用表单初始化,每一个表单字段对应一条数据,它们的HTML name属性即为key值,它们value属性对应value值。
1.模拟HTML表单,相当于将HTML表单映射成表单对象,自动将表单对象中的数据拼接成请求参数的格式。
2.异步上传二进制文件
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.提交表单对象
xhr.send(formData);注意: 1.Formdata 对象不能用于 get 请求,因为对象需要被传递到 send 方法中,而 get 请求方式的请求参数只能放在请求地址的后面。
2.服务器端 bodyParser 模块不能解析 formData 对象表单数据,我们需要使用 formidable 模块进行解析。
1.获取表单对象中属性的值
formData.get('key');2.设置表单对象中属性的值
formData.set('key', 'value');3.删除表单对象中属性的值
formData.delete('key');4.向表单对象中追加属性值
formData.append('key', 'value');注:set 方法与 append 方法的区别是,在属性名已存在的情况下,set 会覆盖已有键名的值,append会保留两个值。
在我们将图片上传到服务器端以后,服务器端通常都会将图片地址做为响应数据传递到客户端,客户端可以从响应数据中获取图片地址,然后将图片再显示在页面中.
xhr.onload = function () { var result = JSON.parse(xhr.responseText); var img = document.createElement('img'); img.src = result.src; img.onload = function () { document.bod y.appendChild(this); } }服务端:
res.send({ path: files.attrName.path.split('public')[1] });客户端:
// 动态创建img标签 var img = document.createElement('img'); // 给图片标签设置src属性 img.src = result.path; // 当图片加载完成以后 img.onload = function () { // 将图片显示在页面中 box.appendChild(img); }Ajax 只能向自己的服务器发送请求。比如现在有一个A网站、有一个B网站,A网站中的 HTML 文件只能向A网站服务器中发送 Ajax 请求,B网站中的 HTML 文件只能向 B 网站中发送 Ajax 请求,但是 A 网站是不能向 B 网站发送 Ajax请求的,同理,B 网站也不能向 A 网站发送 Ajax请求。
如果两个页面拥有相同的协议、域名和端口,那么这两个页面就属于同一个源,其中只要有一个不相同,就是不同源。 http://www.example.com/dir/page.html
http://www.example.com/dir2/other.html:同源 http://example.com/dir/other.html:不同源(域名不同) http://v2.www.example.com/dir/other.html:不同源(域名不同) http://www.example.com:81/dir/other.html:不同源(端口不同) https://www.example.com/dir/page.html:不同源(协议不同)
1.同源政策是为了保证用户信息的安全,防止恶意的网站窃取数据。最初的同源政策是指 A 网站在客户端设置的 Cookie,B网站是不能访问的。
2.随着互联网的发展,同源政策也越来越严格,在不同源的情况下,其中有一项规定就是无法向非同源地址发送Ajax 请求,如果请求,浏览器就会报错。
jsonp 是 json with padding 的缩写,它不属于 Ajax 请求,但它可以模拟 Ajax 请求 具体JSONP讲解:JSONP 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(要定义在script标签前面)
function fn (data) { }4.在 fn 函数内部对服务器端返回的数据进行处理
function fn (data) { console.log(data); }1.客户端需要将函数名称传递到服务器端。
<script src="http://localhost:3001/better?callback=fn2"></script> app.get('/better', (req, res) => { const fnName = req.query.callback; }2.将 script 请求的发送变成动态请求。
<script type="text/javascript"> // 获取按钮 var btn = document.getElementById('btn'); // 为按钮添加点击事件 btn.onclick = function () { // 创建script标签 var script = document.createElement('script'); // 设置src属性 script.src = 'http://localhost:3001/better?callback=fn2'; // 将script标签追加到页面中 document.body.appendChild(script); // 为script标签添加onload事件 script.onload = function () { // 将body中的script标签删除掉 document.body.removeChild(script); } } </script>3.封装 jsonp 函数,方便请求发送。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <button id="btn1">点我发送请求</button> <button id="btn2">点我发送请求</button> <script type="text/javascript"> // 获取按钮 var btn1 = document.getElementById('btn1'); var btn2 = document.getElementById('btn2'); // 为按钮添加点击事件 btn1.onclick = function () { jsonp({ // 请求地址 url: 'http://localhost:3001/better', data: { name: 'lisi', age: 30 }, success: function (data) { console.log(123) console.log(data) } }) } btn2.onclick = function () { jsonp({ // 请求地址 url: 'http://localhost:3001/better', success: function (data) { console.log(456789) console.log(data) } }) } 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); } } </script> </body> </html>4.服务器端代码优化之 res.jsonp 方法。 优化前:
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}); });同源政策是浏览器给予Ajax技术的限制,服务器端是不存在同源政策限制。 使用第三方模块request 1号服务器:
const request = require('request'); app.get('/server', (req, res) => { request('http://localhost:3001/cross', (err, response, body) => { res.send(body); }) });2号服务端:
app.get('/cross', (req, res) => { res.send('ok') });cookie详解
1.在使用Ajax技术发送跨域请求时,默认情况下不会在请求中携带cookie信息。
2.withCredentials:指定在涉及到跨域请求时,是否携带cookie信息,默认值为false
3.Access-Control-Allow-Credentials:true 允许客户端发送请求时携带cookie 示例: 客户端:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>实现跨域功能</title> <link rel="stylesheet" href="/assets/bootstrap/dist/css/bootstrap.min.css"> <style type="text/css"> .container { padding-top: 60px; } </style> </head> <body> <div class="container"> <form id="loginForm"> <div class="form-group"> <label>用户名</label> <input type="text" name="username" class="form-control" placeholder="请输入用户名"> </div> <div class="form-group"> <label>密码</label> <input type="password" name="password" class="form-control" placeholder="请输入用密码"> </div> <input type="button" class="btn btn-default" value="登录" id="loginBtn"> <input type="button" class="btn btn-default" value="检测用户登录状态" id="checkLogin"> </form> </div> <script type="text/javascript"> // 获取登录按钮 var loginBtn = document.getElementById('loginBtn'); // 获取检测登录状态按钮 var checkLogin = document.getElementById('checkLogin'); // 获取登录表单 var loginForm = document.getElementById('loginForm'); // 为登录按钮添加点击事件 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); } } // 当检测用户状态按钮被点击时 checkLogin.onclick = function () { // 创建ajax对象 var xhr = new XMLHttpRequest(); // 对ajax对象进行配置 xhr.open('get', 'http://localhost:3001/checkLogin'); // 当发送跨域请求时,携带cookie信息 xhr.withCredentials = true; // 发送请求并传递请求参数 xhr.send(); // 监听服务器端给予的响应内容 xhr.onload = function () { console.log(xhr.responseText); } } </script> </body> </html>服务端:
// 拦截所有请求 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(); }); app.post('/login', (req, res) => { // 创建表单解析对象 var form = formidable.IncomingForm(); // 解析表单 form.parse(req, (err, fields, file) => { // 接收客户端传递过来的用户名和密码 const { username, password } = fields; // 用户名密码比对 if (username == 'itheima' && password == '123456') { // 设置session req.session.isLogin = true; res.send({message: '登录成功'}); } else { res.send({message: '登录失败, 用户名或密码错误'}); } }) }); app.get('/checkLogin', (req, res) => { // 判断用户是否处于登录状态 if (req.session.isLogin) { res.send({message: '处于登录状态'}) } else { res.send({message: '处于未登录状态'}) } });1.作用:发送Ajax请求。
contentType:传递的对象属性类型。
BeforeSend:请求发送之前调用。 示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>$.ajax方法基本使用</title> </head> <body> <button id="btn">发送请求</button> <script src="/js/jquery.min.js"></script> <script> $('#btn').on('click', function () { $.ajax({ // 请求方式 type: 'post', // 请求地址 url: '/base', // 请求成功以后函数被调用 success: function (response) { // response为服务器端返回的数据 // 方法内部会自动将json字符串转换为json对象 console.log(response); }, // 请求失败以后函数被调用 error: function (xhr) { console.log(xhr) } }) }); </script> </body> </html>url:'/base', :如果域名协议端口一致,可缩写(url:'http://localhost:3000/base',)
默认情况下 两种传递参数的方法都可以:
// 向服务器端发送的请求参数 // name=zhangsan&age=100 // data: { // name: 'zhangsan', // age: 100 // },即:
contentType: 'application/json' contentType: 'application/x-www-form-urlencoded'//默认类型如果服务端要求是json类型参数:
<script> var params = {name: 'wangwu', age: 300} $('#btn').on('click', function () { $.ajax({ // 请求方式 type: 'post', // 请求地址 url: '/user', // 向服务器端发送的请求参数 // name=zhangsan&age=100 // data: { // name: 'zhangsan', // age: 100 // }, data: JSON.stringify(params), // 指定参数的格式类型 contentType: 'application/json', // 请求成功以后函数被调用 success: function (response) { // response为服务器端返回的数据 // 方法内部会自动将json字符串转换为json对象 console.log(response); } }) }); </script>打开网页会首先弹出alert的内容,点击确定以后才会发送请求。
1.作用:发送jsonp请求。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>$.ajax方法基本使用</title> </head> <body> <button id="btn">发送请求</button> <script src="/js/jquery.min.js"></script> <script> function fn (response) { console.log(response) } $('#btn').on('click', function () { $.ajax({ url: '/jsonp', // 向服务器端传递函数名字的参数名称 jsonp: 'cb', jsonpCallback: 'fn', // 代表现在要发送的是jsonp请求 dataType: 'jsonp'/*, success: function (response) { console.log(response) }*/ }) }); </script> </body> </html>作用:将表单中的数据自动拼接成字符串类型的参数
var params = $('#form').serialize(); // name=zhangsan&age=30但是JQuery中没有提供将数据转化成对象类型的方法,需要自己动手封装一个方法来转换:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>serialize方法说明</title> </head> <body> <form id="form"> <input type="text" name="username"> <input type="password" name="password"> <input type="submit" value="提交"> </form> <script src="/js/jquery.min.js"></script> <script type="text/javascript"> $('#form').on('submit', function () { // 将表单内容拼接成字符串类型的参数 // var params = $('#form').serialize(); // console.log(params) serializeObject($(this)); return false; }); // 将表单中用户输入的内容转换为对象类型 function serializeObject (obj) { // 处理结果对象 var result = {}; // [{name: 'username', value: '用户输入的内容'}, {name: 'password', value: '123456'}] var params = obj.serializeArray(); // 循环数组 将数组转换为对象类型 $.each(params, function (index, value) { result[value.name] = value.value; }) // 将处理的结果返回到函数外部 return result; } </script> </body> </html>代码解释:
result[value.name] = value.value //第一次循环 //value.name=username //value.value=zhangsan(第一个value是索引,第二个value是输入的值) var params = obj.serializeArray(); //将输入的数据存到数组1.作用:$ .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) {}) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>$.ajax方法基本使用</title> </head> <body> <button id="btn">发送请求</button> <script src="/js/jquery.min.js"></script> <script> $('#btn').on('click', function () { // $.get('/base', 'name=zhangsan&age=30', function (response) { // console.log(response) // }) $.post('/base', function (response) { console.log(response) }) }); </script> </body> </html>只要页面中有Ajax请求被发送,对应的全局事件就会被触发.
.ajaxStart() // 当请求开始发送时触发 .ajaxComplete() // 当请求完成时触发要绑定在document身上。
1.纳米级进度条,使用逼真的涓流动画来告诉用户正在发生的事情! 引入:
<link rel='stylesheet' href='nprogress.css'/> <script src='nprogress.js'></script>使用:
NProgress.start(); // 进度条开始运动 NProgress.done(); // 进度条结束运动1.一套关于设计请求的规范。
GET: 获取数据 POST: 添加数据 PUT: 更新数据 DELETE: 删除数据 users => /users articles => /articles2.传统请求地址回顾:
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 // 删除用户信息3.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.get('/users', (req, res) => { res.send('当前是获取用户列表信息的路由'); }); // 获取某一个用户具体信息的路由 app.get('/users/:id', (req, res) => { // 获取客户端传递过来的用户id const id = req.params.id; res.send(`当前我们是在获取id为${id}用户信息`); }); // 删除某一个用户 app.delete('/users/:id', (req, res) => { // 获取客户端传递过来的用户id const id = req.params.id; res.send(`当前我们是在删除id为${id}用户信息`); }); // 修改某一个用户的信息 app.put('/users/:id', (req, res) => { // 获取客户端传递过来的用户id const id = req.params.id; res.send(`当前我们是在修改id为${id}用户信息`); }); <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script src="/js/jquery.min.js"></script> <script type="text/javascript"> // 获取用户列表信息 $.ajax({ type: 'get', url: '/users', success: function (response) { console.log(response) } }) // 获取id为1的用户信息 $.ajax({ type: 'get', url: '/users/1', success: function (response) { console.log(response) } }) // 获取id为1的用户信息 $.ajax({ type: 'delete', url: '/users/10', success: function (response) { console.log(response) } }) // 获取id为1的用户信息 $.ajax({ type: 'put', url: '/users/10', success: function (response) { console.log(response) } }) </script> </body> </html>1.XML 的全称是 extensible markup language,代表可扩展标记语言,它的作用是传输和存储数据。
<students> <student> <sid>001</sid> <name>张三</name> </student> <student> <sid>002</sid> <name>王二丫</name> </student> </students>XML教程
XML DOM 即 XML 文档对象模型,是 w3c 组织定义的一套操作 XML 文档对象的API。浏览器会将 XML 文档解析成文档对象模型。 XML DOM详解 示例: 客户端:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <button id="btn">发送请求</button> <div id="container"></div> <script type="text/javascript"> var btn = document.getElementById('btn'); var container = document.getElementById('container'); btn.onclick = function () { var xhr = new XMLHttpRequest(); xhr.open('get', '/xml'); xhr.send(); xhr.onload = function () { // xhr.responseXML 获取服务器端返回的xml数据 var xmlDocument = xhr.responseXML; var title = xmlDocument.getElementsByTagName('title')[0].innerHTML; container.innerHTML = title; } } </script> </body> </html>服务端:
app.get('/xml', (req, res) => { res.header('content-type', 'text/xml'); res.send('<message><title>消息标题</title><content>消息内容</content></message>') });效果: 完。