jQuery源码解析----模拟核心buildFragment

一、代码解析

 1 var $newdiv1 = $('<div id="object1"/>'),
 2     newdiv2 = document.createElement('div'),
 3     existingdiv1 = document.getElementById('foo');
 4 
 5 
 6     var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
 7     var wrapMap = {
 8         // Support: IE 9
 9         option: [1, "<select multiple='multiple'>", "</select>"],
10         thead: [1, "<table>", "</table>"],
11         col: [2, "<table><colgroup>", "</colgroup></table>"],
12         tr: [2, "<table><tbody>", "</tbody></table>"],
13         td: [3, "<table><tbody><tr>", "</tr></tbody></table>"],
14         _default: [0, "", ""]
15     };
16     // Support: IE 9
17     wrapMap.optgroup = wrapMap.option;
18     wrapMap.tbody    = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
19     wrapMap.th       = wrapMap.td;
20 
21 
22     function buildFragment(elems, context) {
23         var elem, tmp, tag, wrap, contains, j,
24             fragment = context.createDocumentFragment(),
25             nodes = [],
26             i = 0,
27             l = elems.length;
28 
29         //筛选出不同类型的节点
30         for (; i < l; i++) {
31             elem = elems[i];
32 
33             if (elem || elem === 0) {
34                 if (jQuery.type(elem) === "object") {
35                     // 如果是jQuery对象
36                     // 如果是普通元素对象加[elem]
37                     // 取出ele放入nodes数组中
38                     jQuery.merge(nodes, elem.nodeType ? [elem] : elem);
39                     // 没有html结构,是一个文本节点
40                 } else if (!/<|&#?\w+;/.test(elem)) {
41                     nodes.push(context.createTextNode(elem));
42                 } else {
43                     //创一个元素div做为容器
44                     tmp = tmp || fragment.appendChild(context.createElement("div"));
45                     tag = (/<([\w:]+)/.exec(elem) || ["", ""])[1].toLowerCase();
46                     //ie对字符串进行trimLeft操作,其余是用户输入处理
47                     //很多标签不能单独作为DIV的子元素
48                     //td,th,tr,tfoot,tbody等等,需要加头尾
49                     wrap = wrapMap[tag] || wrapMap._default;
50                     tmp.innerHTML = wrap[1] + elem.replace(rxhtmlTag, "<$1></$2>") + wrap[2];
51 
52                     // 因为warp被包装过
53                     // 需要找到正确的元素父级
54                                         //定位到最底层的元素
55                     j = wrap[0];
56                     while (j--) {
57                         tmp = tmp.lastChild;
58                     }
59                     // Support: QtWebKit
60                     // jQuery.merge because push.apply(_, arraylike) throws
61                     // 把节点拷贝到nodes数组中去
62                     jQuery.merge(nodes, tmp.childNodes);
63                 }
64             }
65         }
66         i = 0;
67         while ((elem = nodes[i++])) {
68                //‘<td>大家好</td>’这条语句也只能插入<td>大家好</td>,不会给该语句外加<table><tbody><tr></tr></tbody></table>
69             fragment.appendChild(elem)
70         }
71         return fragment;
72     }
73 
74 
75 
76 $('#test1').click(function() {
77     "<table><tbody><tr><td>慕课网</td></tr></tbody></table>"
78     $('body').append($newdiv1, [newdiv2, existingdiv1, '<td>慕课网</td>', '文本', '<script>alert(1)'])
79 })
80 
81 $('#test2').click(function() {
82     //6中类型的数据结构
83     //这里不设计script的执行
84     var fragment = buildFragment([$newdiv1, newdiv2, existingdiv1, '<td>慕课网</td>', '文本', '<script>alert(1)'], document)
85     document.body.appendChild(fragment)
86 })        

 

posted @ 2018-05-03 15:36  T&Y  阅读(113)  评论(0编辑  收藏  举报