框架结构的解析

block
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
(function (global) {
var init;
function fe(selector) {
// 利用工厂模式来返回fe.fn.init对象
return new fe.fn.init(selector);
}
// fn 为 prototype的简写方式。
// 目的:为了方便用户在原型上扩展成员
fe.fn = fe.prototype = {
constructor: fe,
//在这里扩展的方法可以扩展根据方法列表进行扩展
};
// 给fe原型添加init方法
init = fe.fn.init = function (selector) {
};
// 由于暴露外部的变量有 fe函数 以及 其原型
// 而用户要给fe原型扩展成员,但是fe函数返回的是init对象,无法访问fe原型上的成员
// 因此让init实例继承自fe原型即可。
init.prototype = fe.fn;
//添加一个扩展的方法这个方法的参数
//只能是对象,喜欢的话可以自己过滤--拷贝继承
fe.extend = fe.fn.extend = function(source) {
var k;
for (k in source) {
this[k] = source[k]
}
};
//这样就可以扩展不同的方法了
fe.extend({
each:function(){},
})
// 暴露给用户
global.$ = global.fe = fe;
}(window));

跨域问题

在说跨域这个问题之前我什么需要了解什么是 同源

同源

同源策略是浏览器的一种安全策略,所谓同源是指,域名,协议,端口完全相同。

跨域

不同源则跨域

我们来举一个例子

例如 :http://www.example.com/

code block

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
http://api.example.com/detail.html
//不同源,域名不同
https//www.example.com/detail.html
//不同源,协议不同
http://www.example.com:8080/detail.html
//不同源,端口不同
http://api.example.com:8080/detail.html
//不同源.域名、端口不同
https://api.example.com/detail.html
//不同源,协议、域名不同
https://www.example.com:8080/detail.html
//不同源,端口、协议不同
http://www.example.com/detail/index.html
//同源,只是目录不同

跨域的解决办法

利用这个iframe标签(这个可以看另一个文件夹)

  1. 顶级域名相同的可以通过domain.name来解决,即同时设置 domain.name = 顶级域名(如example.com)
  2. document.domain + iframe(比较重要)
  3. window.name + iframe
  4. location.hash + iframe
  5. window.postMessage()

具体的实现

因为是同域名:协议,端口,域名相同的情况下,我是可以去访问
另一个页面中的里面的资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<body>
<iframe src="访问的URL" width="100%" frameborder="0"></iframe>
<script>
/*
我想在这个页面,访问URL
* 页面的dom 元素
*
* */
var iframe=document.querySelector("iframe");
iframe.onload=function(){
document.domain="aichen.com"//(重要)
var win=this.contentWindow;
win.document.querySelector("p").color="blue";
}
//这样既实现了访问的url页面之中操作上面的p标签。
</script>
</body>
**link**只能载入这个css文件。
<!-- link 标签引入css,实际上它也是去发送一个请求的能不能去载入
http://static.meilishuo.net/pc/css/base.css?
1608231432.25找个站点的css 文件.-->
<link href="http://static.meilishuo.net/
pc/css/base.css?1608231432.25"
type="text/css" rel="stylesheet">

jsonp

JSON with Padding

原理剖析

  • 其本质是利用了和link标签页
    是可以用来访问另一个网站的样式.

  • 标签具有可跨域的特性,由服务端 返回一个预先定义好的Javascript函数的调用,并且将服务器数据以该函数参数的形式传递过来,此方法需要前后端配合完成。

  • 只能以GET方式请求

具体的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//实质上就是这个的。
document.querySelector("#buttonId").onclick=function(){
//创建标签,创建script 标签,<script><script>
var script=document.createElement("script");
//<script src=""><script>
script.setAttribute("src","04jsonp.php?username=18");
//我现在这些操作都在dom 里面,都在内存里面。
//我把这个标签放在页面上面.
//也就是说
console.log(script);
document.querySelector("body").appendChild(script);
//因为我现在是我在浏览器使用script 标签发送一个请求给服务器
//服务器返回返回数据,返回的找个数据直接由浏览器进行解析.
//因为我现在是使用的是script 标签,服务器返回的数据
//浏览器默认使用js 去取解析服务器返回的数据。
}

jq 中的一些请求

jQuery 的$.ajax()方法
当中集成了JSONP的实现,可以非常方便的实现跨域数据的访问。

dataType: ‘jsonp’ 设置dataType值为jsonp即开启跨域访问
jsonp 可以指定服务端接收的参数的“key”值,默认为callback
jsonpCallback 可以指定相应的回调函数,默认自动生成

实现不从缓存中读取数据:本代码端中的最后几行注释中就有说明这个问题

  1. $getScript(url,function(){})

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $(function(){
    $("#buttonId").click(function(){
    //getScript 从在面上面去理解我们是获取一段js 脚本.
    //我假设我的页面非常庞大,我不可能一次性把所有的当前页面的这些
    //内容全部加载完毕,只有需要使用到的时候才去记载
    //我们ajax 可以用来做性能优化.
    //我调用这个方法getScript 方法,然后底层是给
    //js/script.js 发送一个请求.
    //它这个是用来处理浏览器缓存的
    $.getScript("js/script.js");
    //当我点击button 我给js/script.js发送请求
    //当我再次点击button 我又去请求js/script.js
    //浏览器会有一些默认行为.
    //当我现在请求的地址js/script.js跟我上次请求的地址js/script.js
    //一样的时候,这个时候浏览器就不会去请求服务器.
    //jQuery 怎么去帮我做js/script.js?_=1474683550796
    //第二次请求地址js/script.js?_=1474683577792
    //浏览器就不会从缓存里面去找了,就会每次都去请求js/script.js
    })
    });
  2. $.ajax

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $.ajax({
    url:"https://sug.so.360.cn/suggest?
    callback=suggest_so&
    encodein=utf-8&encodeout=utf-8&
    format=json&fields=word,obdata&word=z",
    type:"get",
    //默认是使用xmlhttpRequest 发送请求,但是有跨域限制
    //添加这个dataType 底层是发送script 标签的请求.
    dataType:"jsonp",
    success:function(){
    }
    })
  3. getJSON

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <script>
    $(function(){
    $("#buttonId").click(function(){
    //这个方法去请求服务器
    //要求服务器返回的数据格式一定是json的数据格式.
    $.getJSON("06getjson.php",function(data){
    //打印的是什么.
    alert(data);
    });
    })
    });
    </script>

其他的在这里就不多说了自行查阅W3C文档

AJAX 请求

介绍

即Asynchronous Javascript And XML,AJAX.不是一门语言,而是对现有持术的综合利用。
本质是在HTTP协议的基础上以异步的方式与服务器进行通信。
不管是同步交互,还是异步交互,只是跟服务器请求的一种方式,交换数据的一种方式。

那么我们先说最实用的东西,然后在对知识升华一下

创建请求的四步骤

XMLHttpRequest 对象是 AJAX 的关键。说白ajax主要的就是这个内容

  1. 第一步:我们需要创建一个对象,用于跟服务器进行交互
    这个对象叫做xmlHttpRequest,这个对象是浏览器给我们提供的
    目的就是用来跟服务器进行数据交互的.
1
var xhr=new XMLHttpRequest;
  1. 第二步:我需要跟服务器进行数据交互,这个时候我需要跟服务端的资源建立一个连接,xhr ,提供了一个方法,叫做open,
  • method:请求的类型;GET 或 POST
  • url:文件在服务器上的位置
  • async:true(异步)或 false(同步)
1
xhr.open("get","get.php",true);
  1. 第三步:我们需要发送数据给服务器,我们应该调用xhr提供的send 方法.
    如果不需要发送数据,我们这个方法也不能省略,我们可以传递一个null过去

    以为是get方式的话这个地方的内容是为空的,如果是post的话方法就不一样这里头的就是数据的内容,POST还得加一个请求头

1
2
3
xhr.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
xhr.send(null);
  1. 第四步:设置一个回调函数,当服务器端有数据返回的时候会调用这个回调函数与服务器交互的过程当中,服务器会不断的给客户端返回状态,如果有 状态返回,则使用该属性 readyState 接收。
    readyState==4 代表服务器已经响应完毕
    status 服务器端返回给客户端的一个状态码,如果返回的是200代表响应成功。 reponseText 用来接收服务器端返回的数据。
1
2
3
4
5
6
7
8
xhr.onreadystatechange=function() {
//说明响应成功.
if(xhr.readyState==4 && xhr.status==200){
//这个是对响应后的数据处理方法多种多种,是情况而定。
var data=xhr.responseText;
alert(data);
}
}

封装到一个变量

  • 封装带一个对象上思想上跟jq是很像的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    var $={
    ajax:function(obj){
    //我要在这里获取到type,url,data ,success
    var xhr=new XMLHttpRequest();
    if(obj.type=="get"){
    obj.url=obj.url+"?"+obj.data;
    obj.data=null;
    }
    xhr.open(obj.type,obj.url);
    if(obj.type=="post"){
    xhr.setRequestHeader("Content-Type",
    "application/x-www-form-urlencoded");
    }
    xhr.send(obj.data);
    xhr.onreadystatechange=function(){
    if(xhr.readyState==4 && xhr.status==200){
    var data1=xhr.responseText;
    //请求完成的时候调用我传递的回调函数.
    obj.success(data1);
    }
    }
    }
    };
  • 调用:

1
2
3
4
5
6
7
8
9
10
$.ajax({
url:"01ajax.php",
type:"get",
data:"username=zhangsan",
success:function(data){
alert(data);
//其他的方法可以在添加
error:function(){
}
});

在jq中的API方法

  • $.ajax({}) 可配置方式发起Ajax请求
  • $.get() 以GET方式发起Ajax请求
  • $.post() 以POST方式发起Ajax请求
  • $(‘form’).serialize() 序列化表单
    (即格式化key=val&key=val)属性名
  • url 接口地址
  • type 请求方式
  • timeout 请求超时
  • dataType 服务器返回格式
  • data 发送请求数据
  • beforeSend: function () {} 请求发起前调用
  • success 成功响应后调用
  • error 错误响应时调用
  • complete 响应完成时调用(包括成功和失败)

兼容问题处理(了解)

1
2
3
4
5
6
7
8
var xhr;
if(XMLHttpRequest){
// 标准的写法
xhr = new XMLHttpRequest;
}else{
// ie5,6的写法
xhr = new ActiveObject("Microsoft.XMLHTTP")
}

知识点的提升

Async = false

注意:我们在open的方法中如果最后一个参数为false一定要记住要send方法放到最后一步去执行,因为我们false的是同步处理,那就一定要等当 readyState 等于 4 且状态为 200时,表示响应已就绪:

readyState的四种状态

  1. 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
  • 0: 请求未初始化
  • 1: 服务器连接已建立
  • 2: 请求已接收
  • 3: 请求处理中
  • 4: 请求已完成,且响应已就绪
  1. 每位数字的具体情况:
  • 0 Uninitialized 初始化状态。XMLHttpRequest 对象已创建或已被 abort() 方法重置。
  • 1 Open open() 方法已调用,但是 send() 方法未调用。请求还没有被发送。
  • 2 Sent Send() 方法已调用,HTTP 请求已发送到 Web 服务器。未接收到响应。
  • 3 Receiving 所有响应头部都已经接收到。响应体开始接收但未完成。
  • 4 Loaded HTTP 响应已经完全接收。

这个方法导致一个 HTTP 请求发送。如果之前没有调用 open(),或者更具体地说,如果 readyState 不是 1,send() 抛出一个异常。否则,它发送一个 HTTP 请求,该请求由以下几部分组成:

XMLHttpRequest.send()

  • 之前调用 open() 时指定的 HTTP 方法、URL 以及认证资格(如果有的话)。
    之前调用 setRequestHeader() 时指定的请求头部(如果有的话)。
    传递给这个方法的 body 参数。
    一旦请求发布了,send() 把 readyState 设置为 2,并触发 onreadystatechange 事件句柄。

  • 如果之前调用的 open() 参数 async 为 false,这个方法会阻塞并不会返回,直到 readyState 为 4 并且服务器的响应被完全接收。否则,如果 async 参数为 true,或者这个参数省略了,send() 立即返回,并且正如后面所介绍的,服务器响应将在一个后台线程中处理。

  • 如果服务器响应带有一个 HTTP 重定向,send() 方法或后台线程自动遵从重定向。当所有的 HTTP 响应头部已经接收,send() 或后台线程把 readyState 设置为 3 并触发 onreadystatechange 事件句柄。如果响应较长,send() 或后台线程可能在状态 3 中触发 onreadystatechange 事件句柄:这可以作为一个下载进度指示器。最后,当响应完成,send() 或后台线程把 readyState 设置为 4,并最后一次触发事件句柄。

++其他方法的调用时候的 readyState 的值是不一样的,详细查看W3C文档++