使用nginx反向代理发起跨域请求

版权声明:Copyright2018TianDiSheng.AllRightsReserved. https://blog.csdn.net/tianxintiandisheng/article/details/81941293

任务5:http://www.jnshu.com/task/2/45/detail//#1
页面文件放在github:https://github.com/Resalee/css_task/tree/master/JS5
任务用时:5月22日-5月26日,用时约36小时。
任务说明
买的服务器到期了,不准备续,在本地做的测试。所以https://resalee.github.io/css_task/JS5/index.html 看不到效果。
遇到的问题
1、找不到psd
任务里面两个地址都是一个网页文件,一开始没仔细看里面的内容,后来直接下载了http://dev.admin.carrots.ptteng.com/的登录页和后台页到本地,最后还是自己写了个登录页,后台页就直接跳转到后台了。这个任务的重点并不是页面,而是Ajax和Nginx的使用。
2、Nginx本地安装使用
2.0 Nginx是啥?
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。
关于本任务,我的理解:
服务器:存放数据,接收数据请求,回应数据请求。A–>B–>A(A:请求方,B:接收方,服务器)
反向代理服务器:接收数据请求,将请求转发给放数据的服务器(本文下面说的目标服务器),然后目标服务器回应请求给代理服务器,代理服务器再回应给请求方。A–>B–>C–>B–>A(A:请求方,B:反向代理服务器,C:目标服务器,真正的接收方)
在本任务中,Nginx既是目标服务器(放了自己写的登录页面),又是反向代理服务器(向后台请求数据,数据来自另一个服务器)。而Ajax的作用就是无刷新获取当前页面的实时数据,与后台的数据交互(验证接收的信息,并给出反馈)。由于安全问题,Ajax的请求的URL不能跨域,所以需要反向代理,将请求通过Nginx转发给目标服务器。(如果不通过反向代理跨域,需要服务器端做设置,具体方法没有深入了解=。=)
参考:
https://baike.baidu.com/item/nginx/3817705
https://zh.wikipedia.org/wiki/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8
2.1 下载系统对应版本,解压即可
http://nginx.org/en/download.html
我是window系统,下载的稳定版

需要注意的是不要解压到中文路径,比如我将nginx文件夹同步到了坚果云,测试配置文件出现1113错误

2.2 通过命令行操作nginx
win+r,输入cmd打开命令行程序,首先要cd到解压后的文件夹,然后通过各命令行操作,我用到的有:
start nginx 启动nginx
nginx -t 检测nginx.conf配置文件是否正确
nginx -s reload 重新加载配置文件,在修改nginx.conf后使用
nginx -s stop 停止nginx
参考:
http://blog.fpliu.com/it/software/Nginx/command
http://nginx.org/en/docs/beginners_guide.html
2.3 其他说明
1、网页文件放在html文件夹(启动nginx后直接进入localhost可以打开nginx的默认欢迎页)
2、配置文件在conf文件夹,名字是nginx.conf
3、可以给右键添加命令行快捷键,直接在文件夹内打开命令行程序,就不需要cd来cd去了
3、Nginx配置反向代理
3.1 什么是反向代理?
正向代理
正向代理是指代理服务器代替用户连接目标服务器,比如翻墙。代理服务器代理的是用户。一个类比是:假设我(用户)找我爸爸(代理服务器)借钱,老爸没钱,于是老爸找我妈(目标服务器)借了钱,然后把钱给了我。我的目的是得到钱(用户访问目标服务器获取资源),而我妈只知道把钱给了我爸(目标服务器对接代理服务器),而不知道实际上是我要钱(不知道代理服务器背后的用户)。

图片来源及参考:
正向代理与反向代理 http://www.cnblogs.com/bass6/p/6257866.html
你也能写个 Shadowsocks https://segmentfault.com/a/1190000011862912
反向代理
反向代理是代理服务器代替目标服务器连接用户。比如CDN服务。代理服务器代理的是目标服务器,功能是将请求发给目标服务器提供服务。一个类比是:我(用户)打电话给10086(代理服务器)找客服(目标服务器)解决问题,我只能通过10086联系客服,不能直接连接客服,而且打给10086后我也不知道系统会分配哪个客服给我。

图片来源及参考:
正向代理—反向代理—NAT小记 https://blog.csdn.net/wenbingoon/article/details/9272979
https://mp.weixin.qq.com/s/ikrI3rmSYs83wdSWqq2QIg
3.2 为什么要配置Nginx反向代理?
通过反向代理获取本地请求的URL(Ajax请求发送的地址),在Ajax里这个请求地址任务5:http://www.jnshu.com/task/2/45/detail//#1
页面文件放在github:https://github.com/Resalee/css_task/tree/master/JS5
任务用时:5月22日-5月26日,用时约36小时。

任务说明

买的服务器到期了,不准备续,在本地做的测试。所以https://resalee.github.io/css_task/JS5/index.html 看不到效果。

遇到的问题

1、找不到psd

任务里面两个地址都是一个网页文件,一开始没仔细看里面的内容,后来直接下载了http://dev.admin.carrots.ptteng.com/的登录页和后台页到本地,最后还是自己写了个登录页,后台页就直接跳转到后台了。这个任务的重点并不是页面,而是Ajax和Nginx的使用。

2、Nginx本地安装使用

2.0 Nginx是啥?

Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。
关于本任务,我的理解:
服务器:存放数据,接收数据请求,回应数据请求。A–>B–>A(A:请求方,B:接收方,服务器)
反向代理服务器:接收数据请求,将请求转发给放数据的服务器(本文下面说的目标服务器),然后目标服务器回应请求给代理服务器,代理服务器再回应给请求方。A–>B–>C–>B–>A(A:请求方,B:反向代理服务器,C:目标服务器,真正的接收方)
在本任务中,Nginx既是目标服务器(放了自己写的登录页面),又是反向代理服务器(向后台请求数据,数据来自另一个服务器)。而Ajax的作用就是无刷新获取当前页面的实时数据,与后台的数据交互(验证接收的信息,并给出反馈)。由于安全问题,Ajax的请求的URL不能跨域,所以需要反向代理,将请求通过Nginx转发给目标服务器。(如果不通过反向代理跨域,需要服务器端做设置,具体方法没有深入了解=。=)
参考:
https://baike.baidu.com/item/nginx/3817705
https://zh.wikipedia.org/wiki/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8

2.1 下载系统对应版本,解压即可

http://nginx.org/en/download.html
我是window系统,下载的稳定版

image.png | left | 610x238

扫描二维码关注公众号,回复: 2904669 查看本文章

需要注意的是不要解压到中文路径,比如我将nginx文件夹同步到了坚果云,测试配置文件出现1113错误

image.png | left | 674x218

2.2 通过命令行操作nginx

win+r,输入cmd打开命令行程序,首先要cd到解压后的文件夹,然后通过各命令行操作,我用到的有:
start nginx 启动nginx
nginx -t 检测nginx.conf配置文件是否正确
nginx -s reload 重新加载配置文件,在修改nginx.conf后使用
nginx -s stop 停止nginx
参考:
http://blog.fpliu.com/it/software/Nginx/command
http://nginx.org/en/docs/beginners_guide.html

2.3 其他说明

1、网页文件放在html文件夹(启动nginx后直接进入localhost可以打开nginx的默认欢迎页)
2、配置文件在conf文件夹,名字是nginx.conf
3、可以给右键添加命令行快捷键,直接在文件夹内打开命令行程序,就不需要cd来cd去了

3、Nginx配置反向代理

3.1 什么是反向代理?

正向代理

正向代理是指代理服务器代替用户连接目标服务器,比如翻墙。代理服务器代理的是用户。一个类比是:假设我(用户)找我爸爸(代理服务器)借钱,老爸没钱,于是老爸找我妈(目标服务器)借了钱,然后把钱给了我。我的目的是得到钱(用户访问目标服务器获取资源),而我妈只知道把钱给了我爸(目标服务器对接代理服务器),而不知道实际上是我要钱(不知道代理服务器背后的用户)。

image.png | left | 534x391

image.png | left | 692x321

图片来源及参考:
正向代理与反向代理 http://www.cnblogs.com/bass6/p/6257866.html
你也能写个 Shadowsocks https://segmentfault.com/a/1190000011862912

反向代理

反向代理是代理服务器代替目标服务器连接用户。比如CDN服务。代理服务器代理的是目标服务器,功能是将请求发给目标服务器提供服务。一个类比是:我(用户)打电话给10086(代理服务器)找客服(目标服务器)解决问题,我只能通过10086联系客服,不能直接连接客服,而且打给10086后我也不知道系统会分配哪个客服给我。

image.png | left | 553x435

image.png | left | 747x369

图片来源及参考:
正向代理—反向代理—NAT小记 https://blog.csdn.net/wenbingoon/article/details/9272979
https://mp.weixin.qq.com/s/ikrI3rmSYs83wdSWqq2QIg

3.2 为什么要配置Nginx反向代理?

通过反向代理获取本地请求的URL(Ajax请求发送的地址),在Ajax里这个请求地址和当前页面是同源的,所以不存在跨域问题。通过Nginx反向代理可以将这个请求转发给目标服务器获取数据,与页面交互。

什么是互联网协议?

可以将互联网分成五层:

image.png | left | 747x444

每一层都是为了完成一种功能,为了实现功能,就需要共同遵守一些规则,这些规则就是“协议”。
每一层都定义了很多协议,这些协议的总称就是“互联网协议”。
实体层:将电脑连起来,通过光缆、电缆、无线电波等,作用是传输0和1的电信号。
链接层:以太网协议确定0和1的分组方式,以方便解读。以太网规定一组电信号构成一个数据包,叫做“帧”,包括标头和数据。数据包的发送地址和接收地址,叫做Mac地址(网卡标识)。以太网通过“广播”(向本网络所有计算机发送数据包,对比标头的Mac地址,与自己的Mac地址相同就接收,不同就丢掉)的方式传递数据包。
网络层(主机到主机):通过IP协议给计算机分配网络地址(网址,即IP协议地址=IP地址),网络地址可以区分不同计算机是否处于同一个子网络。这样每台计算机就有Mac地址和网络地址,网络地址帮我们确定计算机所在的子网络,Mac地址则将数据包发送到该子网络中的目标网卡。
传输层(端口到端口):有了MAC地址和IP地址,我们可以在任意两台主机上建立通信,但为了识别数据包对应的使用程序(进程),我们还需要一个参数,这个参数就是“端口”(port),它是每一个使用网卡的程序的编号。通过UDP协议(用户数据报协议)给数据包加入端口信息,但UDP协议无法确定是否收到,所以TCP协议(传输控制协议)应运而生,以确保数据不会丢失。
应用层:应用层的作用是规定程序的数据格式,以方便解读。
写一下加深印象,具体参考阮一峰老师的:http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html
http://www.ruanyifeng.com/blog/2012/06/internet_protocol_suite_part_ii.html

什么是HTTP协议?

HTTP协议(超文本传输协议)是互联网协议中的一种,基于 TCP/IP 协议,属于应用层协议,是用于从服务器传输超文本到本地浏览器的传送协议。

image.png | left | 551x181

参考:
http://www.ruanyifeng.com/blog/2016/08/http.html
https://www.jianshu.com/p/80e25cb1d81a

什么是GET、POST?

Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET,POST,PUT,DELETE。GET用于获取数据,通过url来传递。POST用于上传数据,把提交的数据放在HTTP包的Body中。GET的安全性和容量都不如POST。
参考:
HTTP Request Methods https://www.w3schools.com/tags/ref_httpmethods.asp

什么是Ajax?

浏览器可以通过JavaScript脚本向服务器发起HTTP请求。Ajax即脚本发起HTTP通信(Asynchronous JavaScript and XML)(异步JavaScript和XML),可以无刷新读取数据。
在任务里使用Ajax获取登录的用户密码,并和后台的数据进行交互(异步请求),验证输入数据,并给出反应:用户不存在、密码错误、用户账号密码正确并登录成功等,这个数据交互的过程都不需要刷新该登录页。
参考:
http://javascript.ruanyifeng.com/bom/ajax.html
https://en.wikipedia.org/wiki/Ajax_(programming)
https://developer.mozilla.org/zh-CN/docs/Web/Guide/AJAX
https://www.w3schools.com/xml/xml_whatis.asp

Ajax如何发起HTTP请求?

Ajax通过XMLHttpRequest对象发出HTTP请求,得到服务器返回的数据后再进行处理。XMLHttpRequest对象用来在浏览器与服务器之间传送数据。

//1、创建创建Ajax对象
var oAjax = new XMLHttpRequest();
//2、连接服务器(打开和服务器的连接)
oAjax.open('GET', url, true);//HTTP方法、连接地址、同步或异步,true为异步
//3、发送数据
oAjax.send();
//4、接收数据
oAjax.onreadystatechange = function(){
  // 通信成功时,状态值为4
  if (oAjax.readyState === 4){
    if (oAjax.status === 200){
      console.log(oAjax.responseText);
    } else {
      console.error(oAjax.statusText);
    }
  }
};

说明:
1、XMLHttpRequest对象的open方法用于指定发送HTTP请求的参数:

void open(
   string method, //method:表示HTTP动词/方法,比如“GET”、“POST”、“PUT”和“DELETE”
   string url, //url: 表示请求发送的网址
   optional boolean async, //async: 格式为布尔值,默认为true,表示请求是否为异步
   optional string user, //user:表示用于认证的用户名,默认为空字符串
   optional string password //password:表示用于认证的密码,默认为空字符串
);

2、send方法用于实际发出HTTP请求。如果不带参数,就表示HTTP请求只包含头信息,也就是只有一个URL,典型例子就是GET请求(get请求本身是通过URL传递数据的);如果带有参数,就表示除了头信息,还带有包含具体数据的信息体,典型例子就是POST请求。send可以传递多种格式的数据。

oAjax.open('POST', 'http://www.example.com/somepage.php', true);

3、onreadystatechange监控请求状态,readyState就是请求状态,readyState的值就代表不同的状态:

0    (未初始化)还没有调用open()方法
1    (载入)已调用send()方法,正在发送请求
2    (载入完成)send()方法完成,已收到全部响应内容
3    (解析)正在解析响应内容
4    (完成)响应内容解析完成,可以在客户端调用了

4、status属性表示请求得到的HTTP状态码,如果通信成功就是200。statusText属性返回一个字符串,表示服务器发送的状态提示。不同于status属性,该属性包含整个状态信息,比如“200 OK”。
5、responseText属性返回从服务器接收到的字符串。

参考:
http://javascript.ruanyifeng.com/bom/ajax.html
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
https://blog.csdn.net/qq_28702545/article/details/51719199
https://blog.csdn.net/mm_gg_201512/article/details/72830000

什么是跨域?

跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。
参考:
http://www.cnblogs.com/hustskyking/archive/2013/03/31/CDS-introduce.html
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
http://www.cnblogs.com/alvinwei1024/p/4626054.html
https://segmentfault.com/a/1190000000718840

为什么Ajax不能跨域?

AJAX只能向同源网址(协议、域名、端口都相同)发出HTTP请求,如果发出跨源请求(跨域请求),就会报错(详见《同源政策》和《CORS机制》两节)。
参考:
同源政策 http://javascript.ruanyifeng.com/bom/same-origin.html
CORS通信 http://javascript.ruanyifeng.com/bom/cors.html
为什么要禁止跨域的 Ajax 请求?https://www.zhihu.com/question/20138568

如何解决跨域问题?/如何设置Nginx反向代理?

任务5是采用Nginx反向代理来解决跨域问题的,方法是在配置文件里服务器处添加反向代理设置:
这样的话,URL带/carrots-admin-ajax/的请求会转发到目标服务器的IP去,比如Ajax里请求的地址/carrots-admin-ajax/a/login(完整的地址就是localhost/carrots-admin-ajax/a/login)会转发到http://dev.admin.carrots.ptteng.com/carrots-admin-ajax/a/login去请求数据。

image.png | left | 460x302

location /carrots-admin-ajax/{
        proxy_pass http://dev.admin.carrots.ptteng.com/;
        }

参考:
用nginx的反向代理机制解决前端跨域问题 https://www.cnblogs.com/gabrielchen/p/5066120.html
NGINX Reverse Proxy https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
远程服务器上nginx安转与基本操作(ip反向代理转发) https://blog.csdn.net/tengxing007/article/details/61615234

4、阻止表单默认提交事件

一开始的HTML结构如下:

<form class="login">
    <input placeholder="用户名" name="username" type="text">
    <input placeholder="密码" name="password" type="password">
    <p id="msg"></p>
    <button id="btn">登录</button>
</form>

这时候点击登录按钮,会提交表单,以默认的get方式,可以在URL看到登录名和密码。
因为如果不规定button的type,会默认给一个submit的类型,button 类型常用于在用户点击按钮时启动 JavaScript 程序,而submit定义提交按钮,用于向服务器发送表单数据。
参考资料后最终通过js来阻止表单的默认提交。一开始确实写的是button的点击事件,不过考虑到无法回车触发事件(也可以写js),相比之下阻止表单默认提交更简洁。
用到的是preventDefault() 方法。

参考:
如何阻止表单的默认提交事件 https://blog.csdn.net/whd526/article/details/78178451
HTML 标签的 type 属性 http://www.w3school.com.cn/tags/att_input_type.asp
preventDefault() 方法 http://www.w3school.com.cn/jsref/event_preventdefault.asp

5、获取input的value值的方法

传统方法可以通过获取input元素,再获取value:

var aValue = document.getElementsByTagName('input');
var name = aValue[0].value;
var pwd = aValue[1].value;
var data ="name="+name+"&pwd="+pwd;//以键值对的形式发给请求地址
//中间省略
oAjax.send(data);

可以用XMLHttpRequest中的FormData对象提取当前页面表单的数据:

var oForm = document.getElementById('login');
var data = new FormData(oForm); //比原来的方法简单很多,特别是在表单数据多的时候更简便
//中间省略
oAjax.send(data);

参考:
系统学习前端之FormData详解 https://segmentfault.com/a/1190000006716454

6、设置数据类型问题

1)情况一:通过getElementsByTagName来获取input元素,再获取value时,使用POST必须加setRequestHeader。
PS. 如果是用jQuery.ajax(),那么可以不设置content-type,默认就是application/x-www-form-urlencoded。

oAjax.setRequestHeader('content-type','application/x-www-form-urlencoded');

2)情况二:通过FormData获取数据时,不需要用setRequestHeader来设置数据类型,加了反而不对,当然这时候的content-type是multipart/form-data,用Chrome时可以看到:

image.png | left | 446x278

查到的相关资料说的是:注意这种类型的发送方式,不能设置请求头部的Content-Type,应交给浏览器来处理(设定Boundary等工作)。这个boundary是分隔符,分割表单项用的。没有指定分隔符后台自然无法通过Current.Request获取表单项了。
估计要彻底明白这个问题的话要对HTTP请求有更深的理解。我粗浅的理解(不一定对)是:get方法通过URL传递数据,通过get发送的数据包头部就包含其数据信息(也就是application/x-www-form-urlencoded类型),所以可以不用设置setRequestHeader,因为接收方知道你发什么类型的数据过来(看资料,get其实也可以通过数据包的body发信息,但一般不这么用)。而POST是将数据放在body里面的,如果不告诉接收方你的数据类型,它可能就无法解读(除了FormData对象,浏览器知道这是表单数据(multipart/form-data),但是因为表单也可能提交多种类型的数据,比如文件或者文本同时传递,所以boundary是用来分割表单的,boundary由1-70个字符组成,不是人为设定的)。

参考:
Content-Type https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
Ajax方式提交表单的常见编码类型总结 https://segmentfault.com/a/1190000004982390
解决错误指定RequestHeader导致后台接受不到FormData数据的问题 https://blog.csdn.net/u010675860/article/details/76079405
Do I need a content type for http get requests?
https://stackoverflow.com/questions/5661596/do-i-need-a-content-type-for-http-get-requests
multipart/form-data与application/octet-stream的区别、application/x-www-form-urlencoded https://blog.csdn.net/wangjun5159/article/details/49644507
谁说 HTTP GET 就不能通过 Body 来发送数据呢? https://unmi.cc/why-http-get-cannot-sent-data-with-reuqest-body/

7、登陆成功时页面如何跳转

尝试用window.location.href和window.open测试 ,遇到的情况如下:
1)没有注意两者的格式,一开始window.open的格式写错,正确的示例:

window.location.href = "http://test.com/"; //location是window对象属性
window.open ("http://test.com/"); //open()是window对象方法,括号,开始写成等号了

2)里面链接的写法,如果不加http:// 的话,会在前面加域名再跳转,即:

window.location.href = "www.test.com/"; //会跳转到localhost/www.test.com
window.open ("www.test.com/"); //会跳转到localhost/www.test.com

3)window.location.href是在当前页面打开,而window.open在新页面打开,用Chrome测试时会拦截弹出窗口,所以一开始没注意,都不知道为啥不跳转。
参考:
Window 对象 http://www.w3school.com.cn/jsref/dom_obj_window.asp
window.location.href和window.open的几种用法和区别 https://blog.csdn.net/sdfdyubo/article/details/59482655

8、jQuery.ajax()用FormData获取不到表单数据

8.1 FormData(someFormElement)

var formdata = new FormData($('#login'));   //我的表格id为login
var formdata = new FormData($('#login')[0]);//这里用$('form')[0]也是一样的

使用第一个变量时,测试FormData获取不到表单数据,而使用上面第二个时可以,为什么?
创建FormData对象时,里面传的应该是表单,也就是DOM对象。而第一个变量实际上是jQuery对象,也就是一个类数组对象,里面除了包含DOM对象,还有其他操作方法。
要将jQuery对象转化为DOM对象,可以通过[index]来获取,或者通过jQuery的.get()方法来获取jQuery对象(类数组)中的DOM节点。

image.png | left | 638x280

image.png | left | 747x395

参考:
FormData() https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData
DOM对象与JQuery对象 http://www.imooc.com/code/8108
JQuery对象转化为DOM对象 http://www.imooc.com/code/8109
The jQuery Object https://learn.jquery.com/using-jquery-core/jquery-object/

8.2 Uncaught TypeError: Illegal invocation

$('#btn').click(function() {
    var formdata = new FormData($('#login')[0]);
    var xhr = $.ajax({
        type: 'POST',
        url: '/carrots-admin-ajax/a/login',
        data: formdata,
        //processData: false,
        //contentType: false,
        success: function() {
            console.log(formdata.get('name'));
            console.log(formdata.get('pwd'));
        }
    })
})

如果不写被注释掉的那两行,会报Uncaught TypeError: Illegal invocation错误。
参考文档可知,jQuery是将数据类型默认设置为application/x-www-form-urlencoded的,而FormData是multipart/form-data类型,并且还有boundary,所以要让jQuery不设置默认的Content-Type,也就是contentType: false。与此同时还要设置processData,这个选项是默认将获取的data转化成一个查询字符串,以配合默认内容类型 “application/x-www-form-urlencoded”,所以也要设置为false以阻止jQuery转化数据。

参考:
jQuery.ajax() http://api.jquery.com/jquery.ajax/
jQuery ajax - ajax() 方法 http://www.w3school.com.cn/jquery/ajax_ajax.asp
How to send FormData objects with Ajax-requests in jQuery?
https://stackoverflow.com/questions/6974684/how-to-send-formdata-objects-with-ajax-requests-in-jquery

9、jQuery ajax - serialize() 获取表单数据

相比用FormData,serialize()更适合本任务,serialize() 方法通过序列化表单值,创建 URL 编码文本字符串,这样不需要创建FormData对象,也不需要修改数据类型和处理数据的方式,FormData可以用在传递多种类型数据。
参考:
jQuery ajax - serialize() 方法 http://www.w3school.com.cn/jquery/ajax_serialize.asp

代码

1、HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" type="text/css" href="index.css">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
    <form id="login" >
        <input placeholder="用户名" name="name" type="text" >
        <input placeholder="密码" name="pwd" type="password" >
        <p id="msg"></p>
        <button id="btn" type="submit" >登录</button>
    </form>
    <script src="ajax.js"></script>
</body>

</html>

2、JavaScript & Ajax

2.1 传统方法

//IE9+
var aValue = document.getElementsByTagName('input');
var oMsg = document.getElementById('msg');
var oBtn = document.getElementById('btn');
var timer = null;

oBtn.onclick = function(event) {
    event.preventDefault();

    var name = aValue[0].value;
    var pwd = aValue[1].value;
    var data = "name=" + name + "&pwd=" + pwd;
    var oAjax = new XMLHttpRequest();

    oAjax.onreadystatechange = function() {
        if (oAjax.readyState == 4 && oAjax.status == 200) {
            var resdata = JSON.parse(oAjax.responseText);
            console.log(name);
            console.log(pwd);
            console.log(resdata);
            if (resdata.code === 0) {
                window.location.href = "http://dev.admin.carrots.ptteng.com/";
            } else {
                clearInterval(timer);
                oMsg.innerHTML = resdata.message;
                timer = setTimeout(function() {
                    oMsg.innerHTML = '';
                }, 3000)
            }
        }
    }

    oAjax.open('POST', '/carrots-admin-ajax/a/login', true);

    oAjax.setRequestHeader('content-type', 'application/x-www-form-urlencoded');

    oAjax.send(data);
}

2.2 使用FormData:

//IE10+
var oForm = document.getElementById('login');
var oMsg = document.getElementById('msg');
var oBtn = document.getElementById('btn');
var timer = null;

oBtn.onclick = function(event) {
    event.preventDefault();

    var data = new FormData(oForm);
    var oAjax = new XMLHttpRequest();

    oAjax.onreadystatechange = function() {

        if (oAjax.readyState == 4 && oAjax.status == 200) {
            var resdata = JSON.parse(oAjax.responseText);
            //console.log(data.get('name')); //IE不支持FormData的get方法
            //console.log(data.get('pwd'));
            console.log(resdata);
            if (resdata.code === 0) {
                window.location.href = "http://dev.admin.carrots.ptteng.com/";
            } else {
                clearInterval(timer);
                oMsg.innerHTML = resdata.message;
                timer = setTimeout(function() {
                    oMsg.innerHTML = '';
                }, 3000)
            }
        }
    }

    oAjax.open('POST', '/carrots-admin-ajax/a/login', true);

    oAjax.send(data);
}

3、jQuery & Ajax

3.1 IE9+ jQuery.post()

//IE9+ jQuery.post()
$("form").on("submit", function() {
    var url = '/carrots-admin-ajax/a/login';
    var formdata = $(this).serialize();
    var timer = null;
    $.post(url, formdata,
        function(data) {
            console.log(formdata);
            console.log(data);
            if (data.code === 0) {
                window.location.href = "http://dev.admin.carrots.ptteng.com/";
            } else {
                clearInterval(timer);
                $('#msg').html(data.message);
                timer = setTimeout(function() {
                    $('#msg').html('');
                }, 3000)
            }
        }, 'json');
    return false;//阻止表单默认提交行为
})

3.2 IE9+ jQuery.ajax()

$("form").on("submit", function() {
    var timer = null;
    $.ajax({
        type: 'POST',
        url: '/carrots-admin-ajax/a/login',
        data: $('#login').serialize(),
        dataType: 'json',
        success: function(data) {
            console.log(data);
            if (data.code === 0) {
                window.location.href = "http://dev.admin.carrots.ptteng.com/";
            } else {
               $('#msg').html(data.message);
                timer = setTimeout(function() {
                    $('#msg').html('');
                }, 3000)
            }
        }
    })
    return false;//阻止表单默认提交行为
})

3.3 IE10+ jQuery.ajax() & FormData

$("form").on("submit", function() {
    var formdata = new FormData($('#login')[0]);
    $.ajax({
        type: 'POST',
        url: '/carrots-admin-ajax/a/login',
        data: formdata,
        processData: false,
        contentType: false,
        dataType: 'json',
        success: function(data) {
            console.log(data);
            if (data.code === 0) {
                window.location.href = "http://dev.admin.carrots.ptteng.com/";
            } else {
                $('#msg').html(data.message);
                timer = setTimeout(function() {
                    $('#msg').html('');
                }, 3000)
            }
        }
    })
    return false; //阻止表单默认提交行为
})

测试

浏览器:IE9

test.gif | center | 747x238

其他版本就不放图了。


技能树.IT修真院
“我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,掌控自己学习的节奏,学习的路上不再迷茫”。
这里是技能树.IT修真院,成千上万的师兄在这里找到了自己的学习路线,学习透明化,成长可见化,师兄1对1免费指导。快来与我一起学习吧~
凭邀请码注册可享受学费减免优惠
我的邀请码:25344308 ,或者你可以直接点击此链接:
修真院注册链接

猜你喜欢

转载自blog.csdn.net/tianxintiandisheng/article/details/81941293