您当前的位置: 首页 >  jquery

第二章 jQuery技术解密 (三)

发布时间:2013-12-28 16:16:00 ,浏览量:0

2.3 破解 jQuery 选择器接口

jQuery 选择器功能强大,但是用法简单,它仅仅提供了一个接口:jQuery(),也可以简写为 $() 。用法如此简单,但又具有如此强大的处理能力,使 jQuery 必然成为众人追捧的对象。

在上一节中,我们重点分析了 jQuery 框架的雏形,而对于选择器并没有深入分析,仅仅提供了一个简单的 DOM 元素选择作为演示,目的是方便读者理解该框架的架设思路和过程。本节将重点研究 jQuery 选择器的设计思路、实现过程和工作原理。

2.3.1 简单但很复杂的黑洞

前面说到,jQuery 提供了惟一的接口 (jQuery() 或者 $()) 使选择器与外界进行交流。那么这个对象是如何生成的呢?

jQuery 框架的基础是查询,即查询文档元素对象,因此我们可以认为 jQuery 对象就是一个选择器,并在此基础上构建和运行查询过滤器。

jQuery 查询的结果是获取 DOM 元素,这些查询到的 DOM 元素又是如何存储的呢?

根据前面的介绍,我们初步了解到它把查询的结果存储到 jQuery 对象内。由于查询的结果可能是单个元素,也可能是集合,因此,jQuery 对象内应该定义了一个集合。这个集合专门负责存放查询到的 DOM 元素。这正如 JavaScript 中的 Function 对象一样,其内部也构建了一个集合对象 Arguments ,专门负责存储函数的参数。

但是,Functiono 对象和 Arguments 是两个相互独立的概念,仅通过 arguments 属性联系在一起。也就是说 Arguments 对象并非是 Function 对象的子对象,或者是它的内部组成部分。而 jQuery 对象与查询结果的数据集合就不同了,它是完全作为 jQuery 对象的一部分而存在的。

另外,jQuery 虽然仅提供了一个入口,但是它的构建并不只局限于从 DOM 文档树中查询到 DOM 元素,DOM 元素也有可能从别的集合中转移过来的,或者是从 HTML 片断生成的等。

例如,类似下面的代码在 jQuery 应用中经常会看到。

$("div.red").css("display", "none"); // 将 class 为 red 的 div 元素隐藏显示

var width = $("div .red").width(); // 获取 div 元素下 class 为 red 的元素的宽度

var html = $(document.getElementById("wrap")).html(); // 获取 id 为 wrap 元素的 innerHTML 值

$("#wrap", document.forms[0]).css("color", "red"); // 将在第一个 form 元素下 id 为 wrap 元素的字体颜色设置为红色

$("

hello,world
").appendTo("#wrap"); // 将 HTML 字符串信息追加到 id 为 wrap 元素的末尾

在 $() 函数中可以包含选择字符串、HTML 字符串、 DOM 对象和数据集合等不同类型的参数。jQuery 是如何分辨这些参数是选择符字符串、HTML字符串、DOM对象或数据集合的呢?

为了方便读者理解这其中的奥妙,我们不妨把 jQuery 框架进行简化,先删除所有方法、函数以及逻辑代码,然后在 init() 构造器中,使用 alert() 方法获取 selector 参数的类型和信息,其代码如下。

[html] view plain copy
  1. <scripttype="text/javascript">
  2. (function(){
  3. varwindow=this;
  4. jQuery=window.jQuery=window.$=function(selector,context){
  5. returnnewjQuery.fn.init(selector,context);
  6. };
  7. jQuery.fn=jQuery.prototype={
  8. init:function(selector,context){
  9. alert(selector);
  10. }
  11. };
  12. })();
  13. window.onload=function(){
  14. $("div.red");//获取"div.red"
  15. $("div.red");//获取"div.red"
  16. $(document.getElementById("wrap"));//获取"[object]"
  17. $("#wrap",document.forms[0]);//获取"#wrap"
  18. $("<div>hello,world
  19. var
  20. window=this,
  21. jQuery=window.jQuery=window.$=function(selector,context){
  22. returnnewjQuery.fn.init(selector,context);
  23. },
  24. quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/;
  25. //jQuery原型对象
  26. //构造jQuery对象的入口
  27. //所有jQuery对象方法都通过jQuery原型对象来继承
  28. jQuery.fn=jQuery.prototype={
  29. //jQuery对象初始化构造器,相当于jQuery对象的类型,由该函数负责创建jQuery对象
  30. //参数说明:selector:选择器的符号,可以是任意数据类型。考虑DOM元素操作需要,该参数应该是包含DOM元素的任何数据
  31. //context:上下文,指定在文档DOM中哪个节点下开始进行查询,默认值为document
  32. init:function(selector,context){
  33. selector=selector||document;//确保selector参数存在,默认值为document
  34. //第一种情况,处理选择符为DOM元素,此时将忽略上下文,即忽略第二个参数
  35. //例如,$(document.getElementById("wrap")),jQuery(DOMElement)匹配DOM元素。
  36. //先使用selector.nodeType判断当selector为元素节点,将length设置为1,
  37. //并且赋值给context,实际上context作为init的第二个参数,
  38. //也意味着它的上下文节点就是selector该点,返回它的$(DOMElement)对象
  39. if(selector.nodeType){//存在nodeType属性,说明选择符是一个DOM元素
  40. this[0]=selector;//直接把当前参数的DOM元素存入类数组中
  41. this.length=1;//设置类数组的长度,以方便遍历访问
  42. this.context=selector;//设置上下文属性
  43. returnthis;//返回jQuery对象,即类数组对象
  44. }
  45. //如果选择符参数为字符串,则进行处理
  46. //例如,$("<div>hello,world
  47. //使用quickExpr正则表达式匹配该选择符字符串,决定是处理HTML字符串,还是处理ID字符串
  48. //quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/
  49. //quickExpr匹配包含<>的字符串或#后跟[a-zA-Z0-9_]或-的字符串
  50. varmatch=quickExpr.exec(selector);
  51. //验证匹配的信息,任何情况下都不是#id
  52. if(match&&(match[1]||!context)){
  53. //第二种情况,处理HTML字符串,类似$(html)->$(array)
  54. if(match[1]){
  55. //selector=jQuery.clean([match[1]],context);
  56. }
  57. //第三种情况,处理ID字符串,类似$("#id")
  58. else{
  59. varelem=document.getElementById(match[3]);//获取该元素确保元素存在
  60. //处理在IE和Opera浏览器下根据name,而不是ID返回元素
  61. if(elem&&elem.id!=match[3]){
  62. //returnjQuery().find(selector);//默认调用document.find()方法
  63. }
  64. //否则将把elem作为元素参数直接调用jQuery()函数,返回jQuery对象
  65. varret=jQuery(elem||[]);
  66. ret.context=document;//设置jQuery对象的上下文属性
  67. ret.selector=selector;//设置jQuery对象的选择符属性
  68. returnret;
  69. }
  70. }else{
  71. //第四种情况,处理jQuery(expression,[context])
  72. //例如,$("div.red")的表达式字符串
  73. //returnjQuery(context).find(selector);
  74. }
  75. }//elseif(jQuery.isFunction(selector))
  76. //第五种情况,处理jQuery(callback),即$(document).ready()的简写
  77. //例如,$(function(){alert("hello,world");}),
  78. //或者$(document).ready(function(){alert("hello,world");});
  79. //returnjQuery(document).ready(selector);
  80. //确保旧的选择符能够通过
  81. if(selector.selector&&selector.context){
  82. this.selector=selector.selector;
  83. this.context=selector.context;
  84. }
  85. //第六种情况,处理类似$(elements)
  86. //returnthis.setArray(jQuery.isArray(selector)?selector:jQuery.makeArray(selector));
  87. }
  88. };
  89. })();
关注
打赏
1688896170
查看更多评论

暂无认证

  • 0浏览

    0关注

    108697博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.1605s