ajax学习

参考:
https://segmentfault.com/a/1190000009251290?utm_source=tuicool&utm_medium=referral

xhr = new XMLHttpRequest();
//XMLHttpRequest {onreadystatechange: null, readyState: 0, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload…}
xhr.open('GET', 'https://www.baidu.com/', true);
//undefined
xhr.send();
//undefined
//(index):1 XMLHttpRequest cannot load https://www.baidu.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.170.131' is therefore not allowed access.

果然是有同源策略的。
这里写图片描述
然后再试试其他的

xhr = new XMLHttpRequest();
xhr.open('GET', '/wp-login.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send();

在浏览器console里输入之后页面没有半点反应。想起可能是没有设置监听器,但是服务器端应该有访问日志。
果然通过查看apache日志/var/log/apache2/access.log,发现确实浏览器发出了这个HTTP请求,但是页面完全没有反应。

...
192.168.170.1 - - [01/May/2017:20:01:48 +0800] "GET /wp-login.php HTTP/1.1" 200 1602 "http://192.168.170.131/?s=%E5%AD%A6%E7%94%9F" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36"

Apache访问日志格式参考:
http://blog.csdn.net/newhappy2008/article/details/7604956

接下来设置一下监听器试试看。完整代码走一遍。

if (xhr){
    xhr.open('GET', '/wp-login.php', true); //以GET请求方式向/wp-login.php发出异步请求
    // 原生ajax会默认使用Content-Type为'text/plain;charset=UTF-8'的方式发送数据
    //xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');//这是POST方法用的
    xhr.onreadystatechange = function(){
        if (xhr.readyState === 4){  // readyState为4表示响应内容解析完成,可以在客户端调用了。
            if (xhr.status === 200){  //这时通过status获取状态码, 若为200则认为此时服务器响应为"成功"
                console.log('[*]执行成功');
            } else {
                console.log('[*]执行出错');
            }
        }
    }
}

当然,我们可以用onload来代替onreadystatechange等于4的情况,因为onload只在状态为4的时候才被调用。代码如下:

xhr.onload = function(){   // 指定onload的监听函数
    if (xhr.status === 200){    //status为200表示请求成功
        console.log('[*]执行成功');
    } else {
        console.log('[*]执行出错');
    }
}

以上便是原生ajax异步请求数据的常见代码。

jQuery中的ajax

jQuery作为一个使用人数最多的js库,其ajax很好地封装了原生ajax的代码,在兼容性和易用性方面都做了很大的提高,让ajax的调用变得非常简单。
下面是一段简单的jQuery的ajax代码:

$.ajax({
    method: 'GET',           // 1.9.0版本之前使用'type'
    url: '/wp-login.php',
    dataType: 'json'
}).done(function() {
    console.log('[*] 执行成功');
}).fail(function() {
    console.log('[*] 执行出错');
});

与原生ajax不同的是,jQuery中默认的Content-Typeapplication/x-www-form-urlencoded;charset=UTF-8

其他js框架如Vue.js, Angular.js, React, Fetch API略。

跨域ajax

介绍了各种各样的ajax API,我们不能避免的一个重要问题就是跨域,这里重点讲解下ajax跨域的处理方式。
处理ajax跨域问题主要有一下4终方式:
1. 利用iframe
2. 利用JSONP
3. 利用代理
4. 利用HTML5提供的XMLHttpRequest Level2

第1种和第2种方式大家应该都非常熟悉,都属于前端的活,这里就不做介绍了,这里主要介绍第3种和第4种方式。

什么是跨域

参考:
http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全方面的限制的同时也给注入iframe或者ajax应用上带来了不少麻烦。
( 现代浏览器在安全性和可用性之间选择了一个平衡点。在遵循同源策略的基础上,选择性地为同源策略”开放了后门”。 例如img script style等标签,都允许垮域引用资源。)
参考:http://www.cnblogs.com/alsy/p/5470772.html
简单的举例来说,就是由于JavaScript同源策略的限制,a.com域名上的js无法操作b.com或是c.a.com域名下的对象。特别注意两点:
第一,如果是协议和端口造成的跨域问题,”前台”是无能为力的。(因为协议和端口都是需要前台和后台共同遵守才能通信,如果服务器端将协议设置成http而把端口设置为80,客户端是无法通过https以及xxx端口访问服务器的);
第二,在跨域问题上,域仅仅是通过“URL的首部”来识别的。而不会去尝试判断相同IP地址对应着两个域,或者两个IP是否是同一个域。“URL的首部”window.location.protocol+window.location.host
即『协议』+『域名』+『端口』
这里写图片描述
注:其实把这个问题用『跨站』是不是会比『跨域』更加准确没有歧义呢?因为『跨域』总是会联想到跨域名。

跨域的方法

document.domain

document.domain是比较常用的跨域的方法。实现最简单但只能用于同一个主域下不同子域之间的跨域请求,比如 foo.comimg.foo.com 之间,img1.foo.comimg2.foo.com 之间。只要把两个页面的document.domain都指向主域就可以了,比如document.domain='foo.com';
如,

<!-- www.a.com上的a.html -->
document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在这里操纵b.html
    alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};

<!-- script.a.com上的b.html -->
document.domain = 'a.com';

这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。
备注:某一页面的domain默认等于window.location.hostname
这里写图片描述
主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。
问题:
1. 安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。
2. 如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

动态创建script

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的js文件,并可以自由执行引入的js文件中的function(包括操作cookie、DOM等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。

window.name

window.name还真是一个可以在各个域之间共享的东西啊!
这里写图片描述
这里的条件是不关闭那个Tab(而不是原文说的不关闭浏览器,因为不同Tab之间是不能传递的)

location.hash

较常用,把传递的数据依附在url上。 例如获取子页面bar.com/b.html的高度及其他数据

postMessage()

HTML5新增方法,现代浏览器及IE8+支持,简单易用高大上。

参考:
JavaScript跨域总结与解决办法
js实现跨域(jsonp, iframe+window.name, iframe+window.domain, iframe+window.postMessage)
说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
JSONP跨域问题的解决方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值