打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
dojo/dom
  • 设值时,会先将字符串转化为dom节点,然后用dom节点替换元素中的子元素;此时如果字符串中有特殊标签开头,比如tbody、thead、tfoot、tr、td、th、caption、colgroup、col等;对于必须存在包装元素的标签,浏览器不会为这些标签补全包装元素,或者统一作为文本处理,或者忽略这些标签
    那我们就有必要对html标签进行一些修正,主要是针对必须存在于包装元素的标签;这些标签作为innerHTML赋值会被浏览器忽略,但是如果作为dom节点直接挂载到dom树中,浏览器会为他们自动创建隐含的包装元素。所以在遇到这些标签开头的html片段时,我们需要手动补全缺失的包装元素。

  下面我们来看一下dom-construct模块是怎么处理的。

  找出所有待补全的元素:tbody、thead、tfoot、tr、td、th、caption、colgroup、col、legend、li;dojo中使用如下结构将某些缺失的标签管理起来:

var tagWrap = {            option: ["select"],            tbody: ["table"],            thead: ["table"],            tfoot: ["table"],            tr: ["table", "tbody"],            td: ["table", "tbody", "tr"],            th: ["table", "thead", "tr"],            legend: ["fieldset"],            caption: ["table"],            colgroup: ["table"],            col: ["table", "colgroup"],            li: ["ul"]        },

  经过下面这一步处理后,tagWrap中的每一项中多了两个属性, eg:tagWrap.tr.pre = "<table><tbody>"和tagWrap.tr.post = "</tbody></table>";

for(var param in tagWrap){        if(tagWrap.hasOwnProperty(param)){            var tw = tagWrap[param];            tw.pre = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">";            tw.post = "</" + tw.reverse().join("></") + ">";        }    }

  

  1、innerHTML方式需要一个额外的元素,作为临时的容器,所以利用一下变量来管理这个额外的元素:

var reTag = /<\s*([\w\:]+)/,//用来判断字符串参数中是否含有html标签masterNode = {},//作为仓库来管理临时容器 masterNum = 0,//z这两个变量用来标识临时容器masterName = "__" + dojo._scopeName + "ToDomId";

  2、toDom方法中,首先创建一个临时容器,是一个div元素:

doc = doc || win.doc;        var masterId = doc[masterName];        if(!masterId){            doc[masterName] = masterId = ++masterNum + "";            masterNode[masterId] = doc.createElement("div");        }

   3、然后判断frag中是否含有html标签,如果含有html标签而且需要我们补全包装元素,则利用上面生成的pre和post补全标签后传递给master这个容器的innerHTML,这一步完成后找到我们传入的html标签对应的dom树,赋值给master;如果不需要包装,直接赋值给master.innerHTML

var match = frag.match(reTag),            tag = match ? match[1].toLowerCase() : "",            master = masterNode[masterId],            wrap, i, fc, df;        if(match && tagWrap[tag]){            wrap = tagWrap[tag];            master.innerHTML = wrap.pre + frag + wrap.post;            for(i = wrap.length; i; --i){                master = master.firstChild;            }        }else{            master.innerHTML = frag;        }

  这里仅是简单的认为如果正则匹配则进行包装处理,按照我的理解,正则的写法应该为:/^<\s*([\w\:]+)/,原因看下面例子:

  第一个表达式子所以报错,就是因为“adffd”这部分在dom中被作为文本节点,文本节点并没有子节点。更改了正则之后,如果不是html标签做开头则统一作为文本节点添加到dom中去。

  4、将html标签转化成dom后,如果仅有一个元素则返回这个元素,否则将转化后的元素,放入到文档片段中。

        if(master.childNodes.length == 1){            return master.removeChild(master.firstChild); // DOMNode        }                df = doc.createDocumentFragment();        while((fc = master.firstChild)){ // intentional assignment            df.appendChild(fc);        }        return df; // DocumentFragment

  参考标准的描述,DocumentFragment是一个轻量级的文档对象,能够提取部分文档的树或创建一个新的文档片段。可以通过appendChild()或insertBefore()将文档片段中内容添加到文档中。在将文档片段作为参数传递给这两个方法时,实际上只会将文档片段的所有子节点添加到相应的位置上;文档片段本身永远不会称为文档树的一部分

 

利用innerHTML标签创建dom元素,并自动补齐缺失的标签,这就是dom-construct模块针对toDOM方法的实现思路。

 1 exports.toDom = function toDom(frag, doc){ 2         // summary: 3         //        instantiates an HTML fragment returning the corresponding DOM. 4         // frag: String 5         //        the HTML fragment 6         // doc: DocumentNode? 7         //        optional document to use when creating DOM nodes, defaults to 8         //        dojo/_base/window.doc if not specified. 9         // returns:10         //        Document fragment, unless it's a single node in which case it returns the node itself11         // example:12         //        Create a table row:13         //    |    require(["dojo/dom-construct"], function(domConstruct){14         //    |        var tr = domConstruct.toDom("<tr><td>First!</td></tr>");15         //    |    });16 17         doc = doc || win.doc;18         var masterId = doc[masterName];19         if(!masterId){20             doc[masterName] = masterId = ++masterNum + "";21             masterNode[masterId] = doc.createElement("div");22         }23 24         if(has("ie") <= 8){25             if(!doc.__dojo_html5_tested && doc.body){26                 html5domfix(doc);27             }28         }29 30         // make sure the frag is a string.31         frag += "";32 33         // find the starting tag, and get node wrapper34         var match = frag.match(reTag),35             tag = match ? match[1].toLowerCase() : "",36             master = masterNode[masterId],37             wrap, i, fc, df;38         if(match && tagWrap[tag]){39             wrap = tagWrap[tag];40             master.innerHTML = wrap.pre + frag + wrap.post;41             for(i = wrap.length; i; --i){42                 master = master.firstChild;43             }44         }else{45             master.innerHTML = frag;46         }47 48         // one node shortcut => return the node itself49         if(master.childNodes.length == 1){50             return master.removeChild(master.firstChild); // DOMNode51         }52 53         // return multiple nodes as a document fragment54         df = doc.createDocumentFragment();55         while((fc = master.firstChild)){ // intentional assignment56             df.appendChild(fc);57         }58         return df; // DocumentFragment59     };

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
SD9006: IE 混淆了 DOM 对象属性(property)及 HTML 标签属性(attribute),造成了对 setAttribute、getAttribute 的不正确实现
HTML DOM 属性
JS中DOM重点基础知识实验(全)
HTMLDOM和XMLDOM
JavaScript基础-07-DOM
常见DOM操作
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服