jQuery源码学习笔记(5)

浏览器测试Support(已移出jQuery,作用单独插件)

根据浏览器是否支持某项特定的功能特性,来决定程序的执行分支

由于$.browser基于navigator.userAgent检测浏览器类型,很容易被用户和浏览器欺骗,并且缺乏灵活性和不够全面。

因此最好避免编写基于特定浏览器的代码。

相对于$.browser,$.support针对浏览器特定特性的检测则更为有效。

$.browser的实现代码如下:

// 用户代理检测正则表达式定义

var rwebkit = /(webkit)[ \/]([\w.]+)/,

ropera = /(opera)(?:.*version)?[\/]([\w.]+)/,

rmsie = /(msie)([\w.]+)/,

rmozilla = /(mozilla)(?:.*?rv:([\w.]+))?/,

// 到处都是把属性取出来,作为局部变量使用,可以减少跨作用域查询,提高性能

userAgent = navigator.userAgent,

// 用户代理匹配结果

browserMatch,

// 实际执行匹配的函数

uaMatch: function( ua ) {

ua = ua.toLowerCase();

// 依次匹配各浏览器

var match = rwebkit.exec( ua ) ||

ropera.exec( ua ) ||

rmsie.exec( ua ) ||

ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||

[];

// match[1] || "" :match[1]为false(空字符串、null、undefined、0等)时,默认为""

// match[2] || "0" :match[2]为false(空字符串、null、undefined、0等)时,默认为"0"

return { browser: match[1] || "", version: match[2] || "0" };},

// 将测试结果保存至jQuery.browser

browserMatch = jQuery.uaMatch(userAgent);

if ( browserMatch.browser ) {

jQuery.browser[ browserMatch.browser ] = true;

jQuery.browser.version = browserMatch.version;

}

// 不推荐使用safari标记,用webkit代替

if ( jQuery.browser.webkit ) {

jQuery.browser.safari = true;

}

Support功能特性检测法

即根据浏览器是否支持某项特定的功能特性,来决定程序的执行分支,这种方法不考虑浏览器类型和版本,也不考虑浏览器升级带来的变化,更加安全、灵活,同时减少了维护工作,因此成为了当下主流的检测方法。例如绑定load事件的代码:

// 兼容事件模型,通过检测浏览器的功能特性,而非嗅探浏览器

if ( document.addEventListener ) {

// 使用较快的加载完毕事件

document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

// 注册window.onload回调函数

window.addEventListener( "load", jQuery.ready, false );

// 如果是IE事件模型

} else if ( document.attachEvent ) {

// 确保在onload之前触发onreadystatechange,可能慢一些但是对iframes更安全

document.attachEvent( "onreadystatechange", DOMContentLoaded );

// 注册window.onload回调函数

window.attachEvent( "onload", jQuery.ready );

// If IE and not a frame

// continually check to see if the document is ready

var toplevel = false;

try {

toplevel = window.frameElement == null;

} catch(e) {}

if ( document.documentElement.doScroll && toplevel ) {

doScrollCheck();

}

}

典型应用:盒模型

盒模型是CSS中的一个概念,CSS 将所有的网页元素都看做是一个矩形框,这个框由元素的内容(content)、内边距(padding)、边框(border)和外边距(margin)组成,

两种盒模型

IE传统模型:width和height属性包括内边距和边框宽度

W3C标准模型:width和height属性不包含边距和边框宽度

尺寸封装

jQueryn封装了这两种盒模型的差异,统一为W3C标准模型,并提供了修正后的接口:如下所示:

接口 计算公式

width, height  content

innerWidth, innerHeight content+padding

outerWidth, outerHeight content+padding+border+可选的margin



Sizzle选择器

工作原理:

选择器表达式:'div>p',

块表达式 'div'、'p'

并列选择器表达式: 'div, p'

块分割器:对选择器表达式从左到右分割出一个个块表达式

查找器:对块表达式进行查找,找到的DOM元素数组叫候选集

过滤器:对块表达式和候选集进行过滤

关系过滤器: 对块表达式之间的关系进行过滤:+ 紧挨着的兄弟关系;> 父子关系;“ ”祖先关系;“~”之后的所有兄弟关系

候选集:查找器的结果,待过滤器进行过滤

映射集:候选集的副本,过滤器和关系过滤器对映射集进行过滤

工作流程:

1.使用块分割器对选择器表达式进行分割,从左向右

如果遇到","分割的并列选择器表达式,只分割到第一个逗号前的选择器表达式1,将剩余部分记录下来。

2.对最后一个块表达式进行查找Sizzle.find,结果放入到候选集set,并将块表达式中匹配的字符串部分删除

3.如果最后一个块表达式不为空(字符串),过滤器Sizzle.filter对set进行过滤

用分割器,对块表达式进行进行分割,查找,放到候选集set,删掉块表达式中已匹配的,剩余的部分记录下来

查找器进行查找匹配,

过滤器对set进行过滤

将以上查找和过滤得到候选集set复制,放入映射集checkSet,后边的过滤操作在checkSet上进行

你可能感兴趣的:(jQuery源码学习笔记(5))