您当前的位置: 首页 >  jquery

第二章 jQuery技术解密 (四)

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

2.3.4 生成 DOM 元素

jQuery.fn.init() 构造函数能够构建 jQuery 对象,并把匹配的 DOM 元素存储在 jQuery 对象内部集合中。jQuery.fn.init() 构造函数可以接收单个的 DOM 元素,也可以接收 DOM 集合。如果接收的是字符串型 ID 值,则直接在文档中查找对应的 DOM 元素,并把它传递给 jQuery 对象;如果接收的是字符串型 HTML 片段,则需要把这个字符串片段生成 DOM 元素。下面我们将重点分析 jQuery 是如何把 HTML 片段生成 DOM 元素的。

在2.3.3节中,我们可以看到 jQuery.fn.init() 构造器通过 jQuery.clean([match[1], context]); 语句实现把 HTML 片段生成 DOM 元素,jQuery.clean() 是一个公共函数。源代码及其注释如下所示。

jQuery.clean() 包含三个参数,其中 elems 和 context 可以支持多种形式的值。Elems 参数可以为数组、类数组、对象结构的形式。数组元素和对象属性可以混合使用。

对于数字类型参数,则会被转换为字符串型,除了字符串型外,其他的都放入返回的数组中,当然对于集合形式只需要读取集合中每个元素即可。

对于字符串型参数,则把它转换成 DOM 元素,再存入返回的数组中。转换的方式是,把 HTML 字符串片段赋值给创建的 div 元素的 innerHTML ,这样就可以把 HTML 字符串片段挂到 DOM 文档树中,从而实现把字符串转换成 DOM 元素。

在转换过程中,应该考虑 HTML 语法约定,因为标签嵌套是有严格限制的,例如,必须存在中。因此在执行转换前,还应该对 HTML 字符串进行预处理,即修正 HTML 标签不规范的用法,这也是 jQuery.clean() 函数的一个重要工作。

[html] view plain copy
  1. <scripttype="text/javascript">
  2. (function(){
  3. var
  4. window=this,
  5. jQuery=window.jQuery=window.$=function(selector,context){
  6. returnnewjQuery.fn.init(selector,context);
  7. },
  8. quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/;
  9. jQuery.fn=jQuery.prototype={
  10. init:function(selector,context){
  11. selector=selector||document;
  12. if(typeofselector=="string"){
  13. varmatch=quickExpr.exec(selector);
  14. if(match&&(match[1]||!context)){
  15. //第二种情况,处理HTML字符串,类似$(html)->$(array)
  16. if(match[1]){
  17. selector=jQuery.clean([match[1]],context);
  18. }
  19. }
  20. }
  21. }
  22. };
  23. jQuery.fn.init.prototype=jQuery.fn;
  24. //jQuery功能扩展函数
  25. jQuery.extend=jQuery.fn.extend=function(obj){
  26. for(varpropinobj){
  27. this[prop]=obj[prop];
  28. }
  29. returnthis;
  30. };
  31. //公共函数扩展
  32. jQuery.extend({
  33. //参数说明:object表示jQuery对象,callback表示回调函数,args回调函数的参数数组
  34. each:function(object,callback,args){
  35. varname,i=0,length=object.length;
  36. if(args){//如果存在回调函数的参数数组
  37. if(length===undefined){//如果object不是jQuery对象
  38. for(nameinobject){//遍历object的属性
  39. if(callback.apply(object[name],args)===false)
  40. //在对象上调用回调函数
  41. break;//如果回调函数返回值为false,则跳出循环
  42. }
  43. }else{
  44. for(;i<length;)//遍历jQuery对象数组
  45. if(callback.apply(object[i++],args)===false)
  46. //在对象上调用回调函数
  47. break;//如果回调函数返回值为false,则跳出循环
  48. }
  49. }else{
  50. if(length===undefined){//如果object不是jQuery对象
  51. for(nameinobject)//遍历object的属性
  52. if(callback.call(object[name],name,object[name])===false)
  53. break;//如果回调函数返回值为false,则跳出循环
  54. }else{//如果object是jQuery对象
  55. for(varvalue=object[0];//遍历jQuery对象数组
  56. i<length&&callback.call(value,i,value)!==false;value=object[++i]){}
  57. }
  58. }
  59. },
  60. //把HTML字符串片段转换成DOM元素
  61. //参数说明:
  62. //elems参数表示多个HTML字符串片段的数据
  63. //context参数表示上下文
  64. //fragment参数表示框架对象
  65. clean:function(elems,context,fragment){
  66. context=context||document;//默认的上下文是document
  67. //在IE中!context.createElement是错误用法,因为它返回的是对象类型,而不是逻辑值,
  68. //故通过返回类型进行判断
  69. if(typeofcontext.createElement=="undefined")
  70. //支持context为jQuery对象,并获取第一个元素
  71. context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;
  72. //如果仅匹配一个标签,且没有指定框架参数,则直接创建DOM元素,并跳过后面的解析
  73. if(!fragment&&elems.length===1&&typeofelems[0]==="string"){
  74. varmatch=/^<(\w+)\s*\/?>$/.exec(elems[0]);
  75. if(match)
  76. return[context.createElement(match[1])];
  77. }
  78. varret=[],scripts=[],div=context.createElement("div");
  79. //匹配每一个HTML字符串片段,并为每一个片段执行回调函数
  80. jQuery.each(elems,function(i,elem){
  81. if(typeofelem==="number")//把数值转换为字符串的高效方法
  82. elem+='';
  83. if(!elem)//如果不存在元素,则返回,或者为''、undefined、false等时也返回
  84. return;
  85. //HTML字符串转换为DOM节点
  86. if(typeofelem==="string"){
  87. //统一转换为XHTML严谨型文档的标签形式,如<div/>的形式修改为<div>
  88. //all--匹配项
  89. //front--第一个捕获组
  90. //tag--第二个捕获组
  91. returntag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?
  92. all:
  93. front+">
  94. //第一种情况:tags以<table>开头但没有<tbody>。在IE生成的元素中可能自动加<tbody>
  95. //第二种情况:thead|tbody|tfoot|colg|cap为tags,那wrap[1]=="<table>"
  96. //TODO
  97. //}
  98. //使用innerHTML,IE会去掉开头的空格节点,因此加上去掉的空格节点
  99. //TODO
  100. //elem从字符转换成了数组
  101. //TODO
  102. }
  103. //如果是DOM元素,则推入数组,否则就合并数组
  104. /*if(elem.nodeType)
  105. ret.push(elem);
  106. else
  107. ret=jQuery.merge(ret,elem);*/
  108. });
  109. //如果指定了第3个参数,即框架对象,则附加到框架对象上
  110. //这段是新增加的,用来处理js代码,同时也取消了form的处理
  111. if(fragment){
  112. //TODO
  113. }
  114. //返回DOM元素集合
  115. returnret;
  116. }
  117. });
  118. })();
  119. window.onload=function(){
  120. varcontext=document.getElementById("wrap");
  121. //测试代码
  122. $("<option/><div/>",context);
  123. };
关注
打赏
1688896170
查看更多评论

暂无认证

  • 0浏览

    0关注

    108697博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

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

微信扫码登录

0.0502s