上层建筑——DOM元素的特性与属性(dojo/dom-prop)

  上一篇讲解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
    };

  如果您觉得这篇文章对您有帮助,请不吝点击右下方“推荐”,谢谢~

时间: 2024-11-09 16:54:47

上层建筑——DOM元素的特性与属性(dojo/dom-prop)的相关文章

上层建筑——DOM元素的特性与属性(dojo/dom-attr)

上一篇返本求源中,我们从DOM基础的角度出发,总结了特性与属性的关系.本文中,我们来看看dojo框架是如何处理特性与属性的.dojo框架中特性的处理位于dojo/dom-attr模块属性的处理为与dojo/dom-prop模块中. attr.set() 方法的函数签名为: require(["dojo/dom-attr"], function(domAttr){ result = domAttr.set("myNode", "someAttr",

返本求源——DOM元素的特性与属性

抛砖引玉 很多前端类库(比如dojo与JQuery)在涉及dom操作时都会见到两个模块:attr.prop.某天代码复查时,见到一段为某节点设置文本的代码: attr.set(node, 'innerText', 'Hello World!') 这段代码执行后并未生效,虽说innerText不是标准属性,尚未被ff支持,可用的是chrome,这个属性是被支持的.既然显示的文本没变,那就查看一下元素吧. innerText被添加到了html标签上,而换成prop模块后,成功的为节点替换文本. 以上

DOM元素的特性和属性

首先来看一下他们的概念: 特性(Attribute):是DOM元素在文档中作为html标签拥有的属性: 属性(Property):是DOM元素在js中作为对象拥有的属性: 首先来了解一下DOM的五个标准特性(id.title.lang.dir.class) 对于标准特性来说,Attribute和Property是同步的,是会自动更新的, 对于自定义的特性来说,他们是不同步的(自定义的特性不会自动 添加到property) HTML5规范对自定义特性做了增强,只要自定义特性以"data-attrN

DOM元素的特性(Attribute)和属性(Property)

1.介绍: 上篇js便签笔记http://www.cnblogs.com/wangfupeng1988/p/3626300.html最后提到了dom元素的Attribute和Property,本文简单介绍一下我的理解. 其实Attribute和Property这两个单词,翻译出来都是“属性”,<js高级程序设计>书中翻译为“特性”和“属性”,以示区别. 简单理解,Attribute就是dom节点自带的属性,例如html中常用的id.class.title.align等: 而Property是这

使用jQuery匹配文档中所有的li元素,返回一个jQuery对象,然后通过数组下标的方式读取jQuery集合中第1个DOM元素,此时返回的是DOM对象,然后调用DOM属性innerHTML,读取该元素 包含的文本信息

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head> <meta htt

关于dom元素的nextSibling的属性使用注意点

博主在进行某次前端开发过程中,使用dom元素的nextSibling属性,用于获取下一个同辈元素,但是却得到非预期结果.代码片段如下 <!DOCTYPE html> <html> <body> <ul> <li id="Coffee">Coffee</li> <li id="Tea">Tea</li> </ul> <button onclick=&quo

dojo/dom源码

dojo/dom源码学习 dojo/dom模块作为一个基础模块,最常用的就是byId方法.除此之外还有isDescendant和setSelectable方法. dom.byId(myId)方法:   各种前端类库都免不了与DOM节点打交道,操作DOM的方法千变万化最终还是要回到原生的那几个方法中,因为类库再快也快不过原生.所以在dom.byId方法中,还是要依靠document.getElementById('myId')方法.假如没有ie,假如不要考虑兼容性,getElementById方法

Dojo操作dom元素的样式

1.使用dom-style的set方法,可以直接设置dom元素的样式属性,这和使用dom元素的style属性效果一样. 2.使用dom-class的replace方法可以替换某个dom元素的样式,add方法可以为dom元素增加样式,remove方法可以移除dom元素的样式 require(["dojo/dom", "dojo/window", 'dojo/dom-style', 'dojo/topic', "dojo/dom-class", &q

js操作dom元素属性和方法

1.用于处理xml文档的dom元素属性 属性名                      描述 childNodes返回当前元素所有子元素的数组 firstChild返回当前元素的第一个下级子元素 lastChild返回当前元素的最后一个子元素 nextSbling返回紧跟在当前元素后面的元素 nodeValue指定表示元素值的读写属性 parentNode返回元素的父节点 previousSibling返回紧邻当前元素之前的的元素 2.用于遍历XML文档的dom元素方法 方法名