dns-prefetch --DNS 预解析技术

查看美拍官方网站的head头,发现有

<link rel="dns-prefetch" href="http://img.app.meitudata.com">

dns-prefetch这是什么鬼?于是研究了一下。

DNS 实现域名到IP的映射。通过域名访问站点,每次请求都要做DNS解析。目前每次DNS解析,通常在200ms以下。针对DNS解析耗时问题,一些浏览器通过DNS Prefetch 来提高访问的流畅性。

什么是 DNS Prefetch ?

DNS Prefetch 是一种DNS 预解析技术,当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行DNS的解析,减少用户等待时间,提高用户体验。

目前支持 DNS Prefetch 的浏览器有 google chrome 和 firefox 3.5

那么在服务端如何控制浏览器端对域名进行预解析那?

如果要浏览器端对特定的域名进行解析,可以再页面中添加link标签实现。例如:

<link rel="dns-prefetch" href="http://imgs.seenvoice.com"/>

如果要控制浏览器端是否对域名进行预解析,可以通过Http header 的x-dns-prefetch-control 属性进行控制。

可惜目前支持上面标签的只有 google chrome 和 firefox3.5

在chrome 中可通过在地址栏中输入 about:histograms/DNS.PrefetchFoundName 和 about:dns 来查看当前浏览器的预解析数据。

[].slice.call(arguments)

我们知道,Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组,除了IE下的节点集合(因为ie下的dom对象是以com对象的形式实现的,js对象与com对象不能进行转换)
如:

1 var a={length:2,0:'first',1:'second'};
2 Array.prototype.slice.call(a);//  ["first", "second"]
3  
4 var a={length:2};
5 Array.prototype.slice.call(a);//  [undefined, undefined]

可能刚开始学习js的童鞋并不是很能理解这句为什么能实现这样的功能。比如我就是一个,所以,来探究一下。

首先,slice有两个用法,一个是String.slice,一个是Array.slice,第一个返回的是字符串,第二个返回的是数组,这里我们看第2个。

Array.prototype.slice.call(arguments)能够将arguments转成数组,那么就是arguments.toArray().slice();到这里,是不是就可以说Array.prototype.slice.call(arguments)的过程就是先将传入进来的第一个参数转为数组,再调用slice?

再看call的用法,如下例子

1 var a = function(){
2      console.log(this);    // 'littledu'
3      console.log(typeof this);      //  Object
4      console.log(this instanceof String);    // true
5 }
6 a.call('littledu');

可以看出,call了后,就把当前函数推入所传参数的作用域中去了,不知道这样说对不对,但反正this就指向了所传进去的对象就肯定的了。
到这里,基本就差不多了,我们可以大胆猜一下slice的内部实现,如下

1 Array.prototype.slice = function(start,end){
2      var result = new Array();
3      start = start || 0;
4      end = end || this.length; //this指向调用的对象,当用了call后,能够改变this的指向,也就是指向传进来的对象,这是关键
5      for(var i = start; i < end; i++){
6           result.push(this[i]);
7      }
8      return result;
9 }

大概就是这样吧,理解就行,不深究。

最后,附个转成数组的通用函数

 1 var toArray = function(s){
 2     try{
 3         return Array.prototype.slice.call(s);
 4     } catch(e){
 5             var arr = [];
 6             for(var i = 0,len = s.length; i < len; i++){
 7                 //arr.push(s[i]);
                   arr[i] = s[i];  //据说这样比push快
 8             }
 9              return arr;
10     }
11 }

CSS浮动清除

方法1:给父级div定义 高度

代码如下:

<style type=”text/css”>
.div1{background:#000;border:1px solid red; /*解决代码*/height:200px;}

.div2{background:#f00;border:1px solid red;height:100px;margin-top:10px}
.left{float:left;width:20%;height:200px;background:#DDD}
.right{float:right;width:70%;height:80px;background:#DDD}

< /style>

<div class=”div1″>
<div class=”left”>我是左浮动</div>
<div class=”right”>我是右浮动</div>
</div>
<div class=”div2″>我是div2</div>

原理:给父级DIV定义固定高度(height),能解决父级DIV 无法获取高度得问题。
优点:代码简洁
缺点:高度被固定死了,是适合内容固定不变的模块。(不推荐使用)

方法2:DIV闭合处,加<div class=”clear”></div> (.clear{clear:both})

代码如下:

<div class=”div1″>
<div class=”left”>我是左浮动</div>
<div class=”right”>我是右浮动</div>
<div class=”clear”></div>
</div>
<div class=”div2″>我是div2</div>

原理:添加一对空的DIV标签,利用css的clear:both属性清除浮动,让父级DIV能够获取高度。
优点:浏览器支持好
缺点:多出了很多空的DIV标签,如果页面中浮动模块多的话,就会出现很多的空置DIV了,这样感觉视乎不是太令人满意。(不推荐使用)

方法3:结尾处加 br标签<br class=”clear”/> (.clear{clear:both})

代码如下:

<div class=”div1″>
<div class=”left”>我是左浮动</div>
<div class=”right”>我是右浮动</div>
<br class=”clear” />
</div>
<div class=”div2″>我是div2</div>

原理及有优缺点同方法2,可做了解,亦不推荐使用。

方法4:让父级div 也一并浮起来

这样做可以初步解决当前的浮动问题。但是也让父级浮动起来了,又会产生新的浮动问题。 不推荐使用

方法5:父级div定义 display:table

原理:将div属性强制变成表格
优点:不解
缺点:会产生新的未知问题。(不推荐使用)

方法6父元素设置 overflow:hidden;

<style type=”text/css”>
.div1{background:#000;border:1px solid red; /*解决代码*/overflow:hidden;zoom:1}

.div2{background:#f00;border:1px solid red;height:100px;margin-top:10px}
.left{float:left;width:20%;height:200px;background:#DDD}
.right{float:right;width:70%;height:80px;background:#DDD}
</style>



<div class=”div1″>
<div class=”left”>我是左浮动</div>
<div class=”right”>我是右浮动</div>
</div>
<div class=”div2″>我是div2</div>

原理:通过设置父元素overflow值设置为hidden;在IE6中还需要触发 hasLayout(zoom:1)
优点:代码简介,不存在结构和语义化问题
缺点:无法显示需要溢出的元素(亦不太推荐使用)

方法7父元素设置 overflow:auto;

原理:原理同方法6,在IE6中还需要触发 hasLayout(zoom:1)
优点:代码简介,不存在结构和语义化问题
缺点:firefox早期版本会无故产生focus,多个嵌套后,firefox某些情况会造成内容全选;IE中 mouseover 造成宽度改变时会出现最外层模块有滚动条等。

方法8:父级div定义 伪类:after 和 zoom

代码如下:

<style type=”text/css”>
.div1{background:#000;border:1px solid red; /*解决代码*/overflow:hidden;zoom:1}

.div2{background:#f00;border:1px solid red;height:100px;margin-top:10px}
.left{float:left;width:20%;height:200px;background:#DDD}
.right{float:right;width:70%;height:80px;background:#DDD}
.clearfix:after { content: “.”;display: block;height: 0;clear: both;visibility: hidden; }
.clearfix {zoom:1;}
</style>

<div class=”div1 clearfix”>
<div class=”left”>我是左浮动</div>
<div class=”right”>我是右浮动</div>
</div>
<div class=”div2″>我是div2</div>

原理:IE8以上和非IE浏览器才支持:after,原理和方法2有点类似,zoom(IE转有属性)可解决ie6,ie7浮动问题
优点:结构和语义化完全正确,代码量也适中,可重复利用率(建议定义公共类)
缺点:代码不是非常简洁(极力推荐使用)

本方法进益求精写法

相对于空标签闭合浮动的方法代码似乎还是有些冗余,通过查询发现Unicode字符里有一个“零宽度空格”,也就是U+200B,这个字符本身是不可见的,所以我们完全可以省略掉 visibility:hidden了

.clearfix:after {content:”\200B”; display:block; height:0; clear:both; }
.clearfix { *zoom:1; } 照顾IE6,IE7就可以了

使用font-size清除inline-block元素之间的间隙

元素间留白间距出现的原因就是标签段之间的空格,因此,去掉HTML中的空格,自然间距就木有了。考虑到代码可读性,显然连成一行的写法是不可取的
有一种方法,使用font-size:0
类似下面的代码:

.space {
    font-size: 0;
}
.space a {
    font-size: 12px;
}

这个方法,基本上可以解决大部分浏览器下inline-block元素之间的间距(IE7等浏览器有时候会有1像素的间距)。不过有个浏览器,就是Chrome, 其默认有最小字体大小限制,因为,考虑到兼容性,我们还需要添加:
类似下面的代码:

.space {
    font-size: 0;
    -webkit-text-size-adjust:none;
}

HTML5学习 之 XMLhttpRequset level1 和 level2的那些事

XMLHttpRequest是一个浏览器接口,使得Javascript可以进行HTTP(S)通信。
最早,微软在IE 5引进了这个接口。因为它太有用,其他浏览器也模仿部署了,ajax操作因此得以诞生。
但是,这个接口一直没有标准化,每家浏览器的实现或多或少有点不同。HTML 5的概念形成后,W3C开始考虑标准化这个接口。2008年2月,就提出了XMLHttpRequest Level 2 草案。

一、XMLHttpRequest对象

 //新建XMLHttpRequest的实例
  var xhr = new XMLHttpRequest();
    //发出HTTP请求。
  xhr.open('GET', 'api.json');
  xhr.send();
//监控XMLHttpRequest对象的状态变化,指定回调函数。
  xhr.onreadystatechange = function(){
    if ( xhr.readyState == 4 && xhr.status == 200 ) {
      alert( xhr.responseText );
    } else {
      alert( xhr.statusText );
    }
  };

上面的代码包含了XMLHttpRequest level1 对象的主要属性:

  • xhr.readyState:XMLHttpRequest对象的状态,等于4表示数据已经接收完毕。
  • xhr.status:服务器返回的状态码,等于200表示一切正常。
  • xhr.responseText:服务器返回的文本数据
  • xhr.responseXML:服务器返回的XML格式的数据
  • xhr.statusText:服务器返回的状态文本。

二、XMLHttpRequest level1 的缺点

  • 只支持文本数据的传送,无法用来读取和上传二进制文件。
  • 传送和接收数据时,没有进度信息,只能提示有没有完成。
  • 受到"同域限制"(Same Origin Policy),只能向同一域名的服务器请求数据。

三、XMLHttpRequest level2的功能

XMLHttpRequest level2对象,针对XMLHttpRequest level1的缺点,做出了大幅改进。

1. 可以设置HTTP请求的时限。
增加了timeout属性,可以设置HTTP请求的时限。
  

xhr.timeout = 3000;
    //将最长等待时间设为3000毫秒。过了这个时限,就自动停止HTTP请求。
    //ontimeout事件,用来指定回调函数。
  xhr.ontimeout = function(event){
    alert('请求超时!');
  }

2. 可以使用FormData对象管理表单数据。

//新建一个FormData对象。
  var formData = new FormData();
//append 添加表单项。
  formData.append('username', '张三');
  formData.append('id', 123456);
  xhr.send(formData);

3. 可以上传文件。

//假定files是一个"选择文件"的表单元素(input[type="file"]),我们将它装入FormData对象。
  var formData = new FormData();
  for (var i = 0; i < files.length;i++) {
    formData.append('files[]', files[i]);
  }
  xhr.send(formData);

4. 可以请求不同域名下的数据(跨域请求)。

服务器端进行header设置。
见我的另外一博客 [CORS-AJAX POST跨域解决方案][1]

5. 可以获得数据传输的进度信息。

XMLHttpRequest Level2对象,传送数据的时候,有一个progress事件,用来返回进度信息。

它分成上传和下载两种情况。下载的progress事件属于XMLHttpRequest对象,上传的progress事件属于XMLHttpRequest.upload对象。
我们先定义progress事件的回调函数。

xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;

然后,在回调函数里面,使用这个事件的一些属性。

function updateProgress(event) {
    if (event.lengthComputable) {
      var percentComplete = event.loaded / event.total;
    }
  }

上面的代码中,event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0。

与progress事件相关的,还有其他五个事件,可以分别指定回调函数:

  1. load事件:传输成功完成。
  2. abort事件:传输被用户取消。
  3. error事件:传输中出现错误。
  4. loadstart事件:传输开始。
  5. loadEnd事件:传输结束,但是不知道成功还是失败。