博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
上层建筑——DOM元素的特性与属性(dojo/dom-prop)
阅读量:7104 次
发布时间:2019-06-28

本文共 5001 字,大约阅读时间需要 16 分钟。

 上一篇讲解dojo/dom-attr的文章中我们知道在某些情况下,attr模块中会交给prop模块来处理。比如:

  • textContent、innerHTML、className、htmlFor、value
  • disabled、checked等无状态特性对应于属性中的布尔变量
  • 事件的处理

  那这一节,我们便来看看prop对于属性的处理。

 

  首先是一个标准名称字典,将要设置的属性名重新命名,避免与保留字的冲突:

exports.names = {        // properties renamed to avoid clashes with reserved words        "class": "className",        "for": "htmlFor",        // properties written as camelCase        tabindex: "tabIndex",        readonly: "readOnly",        colspan: "colSpan",        frameborder: "frameBorder",        rowspan: "rowSpan",        textcontent: "textContent",        valuetype: "valueType"    };

 相比dom-attr来说,dom-prop模块只有两个公共函数:prop.get与prop.set

  prop.get方法的函数签名为:

// Dojo 1.7+ (AMD)require(["dojo/dom-prop"], function(domProp){  result = domProp.get("myNode", "someAttr");});
除了textContent属性外,其他直接以方括号语法从node中取值:node[prop];对于textContent属性,如果元素不支持textContent,便以深度优先算法去获取元素下所有文本节点的nodevalue:

function getText(/*DOMNode*/node){        var text = "", ch = node.childNodes;        for(var i = 0, n; n = ch[i]; i++){            //Skip comments.            if(n.nodeType != 8){                if(n.nodeType == 1){                    text += getText(n);                }else{                    text += n.nodeValue;                }            }        }        return text;    }
因为innerText并不是标准属性,所以这里弃之不用;以下便是get方法的源码:

exports.get = function getProp(/*DOMNode|String*/ node, /*String*/ name){        node = dom.byId(node);        //转化成标准属性        var lc = name.toLowerCase(), propName = exports.names[lc] || name;    //处理textContent这种特殊属性        if(propName == "textContent" && !has("dom-textContent")){            return getText(node);        }                return node[propName];    // Anything    };
prop.set方法的函数签名为:

require(["dojo/dom-prop"], function(domProp){  result = domProp.set("myNode", "someAttr", "value");});

  在attr.set方法中,很多情况都交给prop来处理,下面我们就要看看prop中set方法的实现。

  set方法用来为元素的属性赋值,在实际应用中需要处理以下几种情况:

  • 参数分解,如果一次设置多个属性,为每个属性分别设置
  • 如果someAttr是“style”,则交给dom-style模块处理
  • 如果someAttr是innerHTML,因为有的元素(tbody、thead、tfoot、tr、td、th、caption、colgroup、col)不支持innerHTML属性,所以需要曲线救国,这里首先将元素的子节点清除掉,然后利用dom-construct的toDom方法,将html片段转化成dom节点,作为子节点插入元素中
  • 如果someAttr是textContent,同样因为有的浏览器并不支持该属性,曲线救国的方式是先清除元素的子节点,然后创建文本节点作为子节点插入元素中
  • 如果value是function,则看做添加事件;对于event的处理最好不要使用prop模块还是推荐使用on模块来绑定事件

exports.set = function setProp(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){        node = dom.byId(node);        var l = arguments.length;        //分解参数        if(l == 2 && typeof name != "string"){ // inline'd type check            for(var x in name){                exports.set(node, x, name[x]);            }            return node; // DomNode        }        //如果要设置style,调用dom-style来处理        var lc = name.toLowerCase(), propName = exports.names[lc] || name;        if(propName == "style" && typeof value != "string"){ // inline'd type check            // special case: setting a style            style.set(node, value);            return node; // DomNode        }        //如果是innerHTML,对于不支持innerHTML的节点,采用曲线救国的方式,否则直接设置innerHTML        if(propName == "innerHTML"){            // special case: assigning HTML            // the hash lists elements with read-only innerHTML on IE            if(has("ie") && node.tagName.toLowerCase() in {col: 1, colgroup: 1,                        table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1}){                ctr.empty(node);                node.appendChild(ctr.toDom(value, node.ownerDocument));            }else{                node[propName] = value;            }            return node; // DomNode        }        //如果不支持textContent,清除元素子节点后,添加文本节点        if(propName == "textContent" && !has("dom-textContent")) {            ctr.empty(node);            node.appendChild(node.ownerDocument.createTextNode(value));            return node;        }        //这一部分是通过prop来绑定事件,但并不建议用这种方式        if(lang.isFunction(value)){            // special case: assigning an event handler            // clobber if we can            var attrId = node[_attrId];            if(!attrId){                attrId = _ctr++;                node[_attrId] = attrId;            }            if(!_evtHdlrMap[attrId]){                _evtHdlrMap[attrId] = {};            }            var h = _evtHdlrMap[attrId][propName];            if(h){                //h.remove(); 如果曾经以类似的方式绑定过事件,则移除事件                conn.disconnect(h);            }else{                try{                    delete node[propName];                }catch(e){}            }            // ensure that event objects are normalized, etc.            if(value){//prop.get函数返回node,所以把handle放到_evtHdlrMap中                //_evtHdlrMap[attrId][propName] = on(node, propName, value);                _evtHdlrMap[attrId][propName] = conn.connect(node, propName, value);            }else{                node[propName] = null;            }            return node; // DomNode        }        node[propName] = value; //直接为属性赋值        return node;    // DomNode    };
如果您觉得这篇文章对您有帮助,请不吝点击右下方“推荐”,谢谢~

转载地址:http://emjhl.baihongyu.com/

你可能感兴趣的文章
Python正则表达式
查看>>
Haproxy 1.4.*安装配置
查看>>
FreeBSD8.2系统安装Salt
查看>>
HP 380G7安装 WIN2008 R2 SP1提示找不到系统分区
查看>>
1.2方程求根之不定点迭代法
查看>>
C#.NET通用权限管理系统组件中让系统按代码生成器的方式运行的方法
查看>>
Mysql主从复制 (suse 11 sp2)
查看>>
jQuery最佳实践
查看>>
gnome-terminal技巧
查看>>
jQuery插件开发全解析
查看>>
Visual Studio 2012/2010/2008 远程调试
查看>>
jsp页面传值的乱码问题总结
查看>>
名不副实的女解说员
查看>>
cacti批量添加主机和图形
查看>>
源代码安装
查看>>
dhcp在企业网的应用
查看>>
thinkphp U方法生成链接没有host
查看>>
ElasticSearch入门介绍之安装部署(二)
查看>>
continue与break的理解
查看>>
我的友情链接
查看>>