解析 DOM 元素里的复杂属性值(下)

我们之前描述过,通过 JavaScript,如何从 DOM 元素的属性中,解析出复杂的值,并转成合适的对象。然而,我们还希望拥有一项更酷炫的技能,那就是提供一个方法,提供一个 DOM 和一些想要获取的属性的名称,然后输出一个对象,这个对象包含一些属性,这些属性刚好就是那个 DOM 上的属性,当 DOM 上的那些属性更新后,对象上的属性也可以支持更新。由此,我们可以拥有一个更面向前端友好的方式去动态获取某个 DOM 节点上所关心的属性内容了。

听起来很棒,但怎么实现呢?废话不多说,我们赶快开始搞定这件事吧!

我们需要提供一个函数,输入的是一个 DOM 元素,以及一个字符串数组,数组里面放的是需要获取的 DOM 属性名称。在这个函数里面,我们需要先遍历所有想要获得的节点,并解析出来,然后做为属性绑定到输出对象上。

function bindAttr(element, names) {
    var ele = !!element && typeof element === "string" ? document.getElementById(element) : element as HTMLElement;
    if (!ele || !ele.tagName || !names) return undefined;
 
    var obj: any = {};
    names.forEach(function (attrName, i, arr) {
        var attr = attr(element, attrName);
        obj[attrName] = attr;
    });
 
    return obj;
}

接下来,我们要开始实现监听事件,并且其本身所需处理的事情与上面的有一些类似,由此一来,当 DOM 中的属性值变化后,会实时反应到返回对象上对应的属性的。

var listener = function (ev) {
    var attrName = ev.attrName || ev.propertyName;
    if (!attrName || !names || !names.some(function (name, ni, narr) {
        return name === attrName;
    })) return;
    var attrObj = attr(element, attrName);
    obj[attrName] = attrObj;
};
ele.addEventListener("DOMAttrModified", listener, false);

当然,这么做了之后,如果需要取消监听怎么办?于是我们想到可以在返回对象上加一个 dispose 方法来搞定;当然,你也可以取别的名字,但最好避免和 DOM 里可能会用到的属性名重名,也就是说前面加个下划线或者搞生僻一些;甚至是你可以把返回属性再包一层。但不管了,这里就用 dispose 方法来演示了。

obj.dispose = function () {
    ele.removeEventListener("DOMAttrModified", listener, false);
};

好了,现在大功告成啦!或许你还可以再优化一下,比如我们加一个参数来控制是否需要监听变动什么的。最终,我们写好了如下完整函数。

/**
  * Binds the objects parsed from specific attributes of an element to an object as its properties.
  * @param element  the element to get attribute.
  * @param names  the attribute name list.
  * @param loadOnce  true if just load once without attribute listening; otherwise, false.
  */
function bindAttr(element: HTMLElement | string, names: string[], loadOnce = false) {
    var ele = !!element && typeof element === "string" ? document.getElementById(element) : element as HTMLElement;
    if (!ele || !ele.tagName || !names) return undefined;
 
    var obj: any = {};
    names.forEach(function (attrName, i, arr) {
        var attr = attr(element, attrName);
        obj[attrName] = attr;
    });
 
    if (!loadOnce) {
        var listener = function (ev) {
            var attrName = ev.attrName || ev.propertyName;
            if (!attrName || !names || !names.some(function (name, ni, narr) {
                return name === attrName;
            })) return;
            var attrObj = attr(element, attrName);
            obj[attrName] = attrObj;
        };
        ele.addEventListener("DOMAttrModified", listener, false);
        obj.dispose = function () {
            ele.removeEventListener("DOMAttrModified", listener, false);
        };
    }
 
    return obj;
}

有没有觉得特别棒?


文章类型及复杂度:Web 进阶。

节选翻译自 MSDN 博文 Parse DOM attribute object,内容有所调整。

http://blogs.msdn.com/b/kingcean/archive/2016/03/18/parse-attribute-object-in-dom.aspx

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值