上层建筑——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", "value");
});

 “someAttr”代表特性名称,但有时候也可以是一些特殊的属性名,如:‘textContent’:

  

  可以看到上图中使用attr设置innerText只会在html标签中增加innerText这个自定义特性,而无法改变文本,使用textContent却能够达到改变文本的目的。其中缘由就是因为在attr模块建立了forceProps字典,在此字典中的key全部使用prop模块来设置:

forcePropNames = {
            innerHTML:    1,
            textContent:1,
            className:    1,
            htmlFor:    has("ie"),
            value:        1
        }

 set()方法中主要处理以下几件事:

  • “someAttr”除了可以是字符串外,还可以是key-value对象,所以对于key-value对象我们首先要进行参数分解。
  • 如果someAttr等于style,就交给dojo/dom-style模块来处理
  • 上篇文章中我们说过,特性值只能是字符串,所以对于函数,默认是作为事件绑定到元素上,这部分交给dojo/dom-prop来处理;另外对于disabled、checked等无状态的属性,在通过属性设置时,只能传递布尔值,所以这部分也交给prop来处理
  • 剩下的交给原生api,setAttribute来处理,这个方法会自动调用value的toString方法
exports.set = function setAttr(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
        node = dom.byId(node);
        if(arguments.length == 2){ // inline'd type check
            // the object form of setter: the 2nd argument is a dictionary
            for(var x in name){
                exports.set(node, x, name[x]);
            }
            return node; // DomNode
        }
        var lc = name.toLowerCase(),
            propName = prop.names[lc] || name,
            forceProp = forcePropNames[propName];
        if(propName == "style" && typeof value != "string"){ // inline'd type check
            // special case: setting a style
            style.set(node, value);
            return node; // DomNode
        }
        if(forceProp || typeof value == "boolean" || lang.isFunction(value)){
            return prop.set(node, name, value);
        }
        // node's attribute
        node.setAttribute(attrNames[lc] || name, value);
        return node; // DomNode
    };

attr.get()

  方法的函数签名为:

// Dojo 1.7+ (AMD)
require(["dojo/dom-attr"], function(domAttr){
  result = domAttr.get("myNode", "someAttr");
});

为了解释方便,我们要先看一下get方法的源码:

exports.get = function getAttr(/*DOMNode|String*/ node, /*String*/ name){
        node = dom.byId(node);
        var lc = name.toLowerCase(),
            propName = prop.names[lc] || name,
            forceProp = forcePropNames[propName],
            value = node[propName];        // should we access this attribute via a property or via getAttribute()?

        if(forceProp && typeof value != "undefined"){
            // node's property
            return value;    // Anything
        }

        if(propName == "textContent"){
            return prop.get(node, propName);
        }

        if(propName != "href" && (typeof value == "boolean" || lang.isFunction(value))){
            // node's property
            return value;    // Anything
        }
        // node's attribute
        // we need _hasAttr() here to guard against IE returning a default value
        var attrName = attrNames[lc] || name;
        return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
    };

  1. 先得到的是三个变量:propName、forceProp、value,
  2. 如果attrName属于forceProps集合,直接返回DOM节点的属性
  3. textContent明显位于forceProps中,为什么还要单独拿出来做判断?因为有的低版本的浏览器不支持textContent,我们需要利用深度优先算法,利用文本的节点的nodeValue由父到子依次拼接文本,这一点jQuery与dojo的思路都是一致的:
    1. dojo: 
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;
    }

    1. jQuery:
  1. set方法中提到过,对于布尔跟函数,交给prop来设置,那么取值时当然也要从prop中来取;至于为什么要单独拿出href,在“返本求源”中已经说过,通过属性得到的href属性跟getAttribute方法得到的值并不一定相同,尤其是非英文字符:
  2. 由prop模块该做的都做完了,所以这里判断node中是否存在该特性时,无需理会forceProps字典;如果存在则调用getAttribute方法。

 

attr.has

  既然可以使用attr来set这些属性,那在attr.has方法中,位于此字典中属性当然也要返回true,所以attr.has(node, attrName)方法主要判断两个方面:

  • attrName是否是forceProps中的key
  • attrName是否是一个特性节点。特性节点为与元素的attributes属性中,可以通过:attributes[attrName] && attributes[attrName].specified 来判断
exports.has = function hasAttr(/*DOMNode|String*/ node, /*String*/ name){
        var lc = name.toLowerCase();
        return forcePropNames[prop.names[lc] || name] || _hasAttr(dom.byId(node), attrNames[lc] || name);    // Boolean
    };
function _hasAttr(node, name){
        var attr = node.getAttributeNode && node.getAttributeNode(name);
        return !!attr && attr.specified; // Boolean
    }

attr.remove

  这个方法比较简单,直接调用了removeAttribute方法

exports.remove = function removeAttr(/*DOMNode|String*/ node, /*String*/ name){
        // summary:
        //        Removes an attribute from an HTML element.
        // node: DOMNode|String
        //        id or reference to the element to remove the attribute from
        // name: String
        //        the name of the attribute to remove

        dom.byId(node).removeAttribute(attrNames[name.toLowerCase()] || name);
    };

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

时间: 2024-08-08 19:43:56

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

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

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

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

上一篇讲解dojo/dom-attr的文章中我们知道在某些情况下,attr模块中会交给prop模块来处理.比如: textContent.innerHTML.className.htmlFor.value disabled.checked等无状态特性对应于属性中的布尔变量 事件的处理 那这一节,我们便来看看prop对于属性的处理.   首先是一个标准名称字典,将要设置的属性名重新命名,避免与保留字的冲突: exports.names = { // properties renamed to av

原生js获取iframe中dom元素--父子页面相互获取对方dom元素的方法_javascript技巧

用原生js在父页面获取iframe子页面的元素,以及在子页面获取父页面元素,这是平时经常会用到的方法,这里写一个例子来总结下: 1.父页面(demo.html),在父页面修改子页面div的背景色为灰色,原来为红色: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

javascript学习笔记(二十) 获得和设置元素的特性(属性)_基础知识

本节html以下面的为例 复制代码 代码如下: <div id="myDiv" class="bd" title="我是div"> <img id="img1" /> <a id="myA" href = "http://www.baidu.com">百度</a> </div> 1.通过HTMLElement类型(对象)的属性获

dom元素-无法获得动态生成的DOM元素

问题描述 无法获得动态生成的DOM元素 $(function(.....))是表示当网页加载完成后,此函数中的js内容才会执行. 可是我现在碰到一个问题. 网页原本的dom元素已经加载完成了,我现在动态生成了一个DOM元素,但在$(function(.....))无法获得刚生成的DOM元素.请问大家是怎么做的? 解决方案 // 创建一个p标签,document.createElement()的返回值就是生成的DOM,就是这里定义的p var p = document.createElement(

JS动态创建DOM元素的方法_javascript技巧

本文实例讲述了JS动态创建DOM元素的方法.分享给大家供大家参考.具体如下: 近日,因工作需要,需要通过点击某个元素后, 动态创建一个DOM元素并显示,因此写了一些相关的JS函数,在此记录,以作备忘: /* 动态创建DOM元素的相关函数支持 */ /* 获取以某个元素的DOM对象 @obj 该元素的ID字符串 */ function getElement(obj) { return typeof obj=='string'?document.getElementById(obj):obj; }

Dojo学习笔记 7. dojo.dom

模块:dojo.dom dojo.dom.isNode 测试指定对象是否为节点 Usage Example: dojo.dom.isNode(dojo.byId('edtTitle')); dojo.dom.getUniqueId 取得唯一id Usage Example: dojo.dom.getUniqueId(); //will return dj_unique_# dojo.dom.firstElement = dojo.dom.getFirstChildElement 取得指定节点下的

《jQuery Cookbook中文版》——1.9 根据当前上下文遍历DOM获得新的DOM元素集

1.9 根据当前上下文遍历DOM获得新的DOM元素集 1.9.1 问题你已经选择了一组DOM元素,根据选择集在DOM结构树中的位置,你打算遍历DOM获得一个新的元素集以供操作. 1.9.2 解决方案jQuery提供一组方法,可以根据当前选择的DOM元素的上下文遍历DOM. 例如,查看如下的HTML片段: <div> <ul> <li><a href="#">link</a></li> <li><a

《jQuery Cookbook中文版》——1.14 获取、设置和删除DOM元素属性

1.14 获取.设置和删除DOM元素属性 1.14.1 问题 你已经用jQuery函数选择了一个DOM元素,需要获取或者设置该元素的属性值. 1.14.2 解决方案 jQuery提供attr()方法以获取和设置属性值.在下面的代码中,将设置< a>元素的href属性值,然后获取该值: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xht