zepto.init()函数里有几个非常重要的函数,zepto.fragment()函数是其中之一。它主要是对生成元素的一个处理,并对生成的dom元素进行返回。例如:$("<p>")或者为他添加属性$("<p>",{height:200px}),就会生成一个新的P元素出来。源码如下:
1 zepto.fragment = function(html, name, properties) { 2 // 内部函数 HTML 转换成 DOM 3 // 原理是 创建父元素,innerHTML转换 4 // @param html html片段 5 // @param name 容器标签名 6 // @param propertie 附加的属性对象 7 // @returns {*} 8 var dom, nodes, container 9 10 // A special case optimization for a single tag 11 //如果是传入单个元素,创建dom 12 if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1)) 13 14 if (!dom) { 15 //修正自闭合标签 如<div />,转换成<div></div> 16 if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>") 17 //给name取元素名 18 if (name === undefined) name = fragmentRE.test(html) && RegExp.$1 19 //设置容器名,如果不是tr,tbody,thead,tfoot,td,th,则容器名为div 20 //为什么设置容器,是严格按照HTML语法,虽然tr td th浏览器会会自动添加tbody 21 if (!(name in containers)) name = '*' 22 //创建容器 23 container = containers[name] 24 //生成dom 25 container.innerHTML = '' + html 26 dom = $.each(slice.call(container.childNodes), function(){ 27 container.removeChild(this) 28 }) 29 } 30 31 if (isPlainObject(properties)) { 32 nodes = $(dom) 33 $.each(properties, function(key, value) { 34 if (methodAttributes.indexOf(key) > -1) nodes[key](value) 35 else nodes.attr(key, value) 36 }) 37 } 38 39 return dom 40 }
函数最上定义了几个变量,然后是这样一段代码:
//如果是传入单个元素,创建dom if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))
· singleTagRE是我们zepto函数中一开始就定义的一个正则表达式,用于探测单个元素,解释如下:
1 //用来匹配取出单个元素 2 // var singleTagRE = /^<(w+)s*/?>(?:</1>|)$/; 3 // var name = (singleTagRE.test("<p></p>")&&RegExp.$1); //这里可以正常匹配<p>,<p/>,<p></p> 4 // console.log(name); 5 // 结果:p 6 singleTagRE = /^<(w+)s*/?>(?:</1>|)$/,
· container是先前定义的一个对象,代码如下,用于判断元素的容器:
1 containers = { 2 'tr': document.createElement('tbody'), 3 'tbody': table, 'thead': table, 'tfoot': table, 4 'td': tableRow, 'th': tableRow, 5 '*': document.createElement('div') 6 },
· isPlainObject是用于判断传入参数obj是否为纯粹的对象(哟个对象字面量{}创建的或者new出来的对象),在这里的用途是为了判断元素是否需要添加属性,例如这样:
$("<p>",{200px,height:200px;})中的第二个参数对象。
1 function isPlainObject(obj) { 2 return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype 3 }