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 })