YUI 读码日记之 YAHOO.util.Dom - Part.1

软件设计 2017-06-07

先绕开头部很多的 if...else (其实就是定义 toCamel 与 getStyle 两个函数) - 由于浏览器的实现不统一,才造成如此麻烦的情况,回头可以聊聊这些代码。

下面我们在 YAHOO.util.Dom 类中看看有哪些宝藏。目前思想已经逐步的分裂,我看见个函数说个函数。

// 基本上可以认为是 document.getElementById 的翻版

get: function(el) {

    // 如果已经是 HTMLElement ,那么就直接返回

    if (el && (el.nodeType || el.item)) {

        return el;

    }

    // 如果是字符串,那么就返回有这个 ID 的 Element

    if (YAHOO.lang.isString(el) || !el) {

        return document.getElementById(el);

    }

    // 看起来是个数组,循环调用自身,获取 Eelement

    if (el.length !== undefined) {

        var c = [];

        for (var i = 0, len = el.length; i < len; ++i) {

            c[c.length] = Y.Dom.get(el[i]);

        }

        return c;

    }

    return el;

},这段代码写得非常的精妙。坦白的说,上述代码中的循环体,如果不加思索的话,恐怕就会写成

for (var i = 0, len = el.length; i < len; ++i) {

    c[c.length] = document.getElementById(el[i]);

}虽然也能正常工作,但是前面的判断就失去了意义。

继续走马观花,现在看看 getElementsByClassName 的内部机制。有关 getElementsByClassName 的详细调用,可以参看 YUI 文档。

getElementsByClassName: function(className, tag, root, apply) {

    // 获取 tag 标签,默认为所有(“*”)

    tag = tag || '*';

    // 指定跟节点名

    root = (root) ? Y.Dom.get(root) : null || document; 

    if (!root) {

        return [];

    }

    // 初始化节点信息

    var nodes = [],

        elements = root.getElementsByTagName(tag),

        re = getClassRegEx(className);

    // 滤掉不符合规则的节点

    for (var i = 0, len = elements.length; i < len; ++i) {

        if ( re.test(elements[i].className) ) {

            // 你一定很奇怪为什么用 nodes.length 而不是用 i

            // 仔细考虑下 :^)

            nodes[nodes.length] = elements[i];

            // 执行回调函数

            if (apply) {

                apply.call(elements[i], elements[i]);

            }

        }

    }

    return nodes;

},教科书式的 DOM 节点获取和过滤,初始化数据以及操作数据都显得非常的严谨而且正规,YUI 的代码让我有几分的“安全感”。类似的,再来一个 getElementsBy 函数,相应代码如下

getElementsBy: function(method, tag, root, apply) {

    // 与上述函数相同,略

    tag = tag || '*';

    root = (root) ? Y.Dom.get(root) : null || document; 

    if (!root) {

        return [];

    }

    var nodes = [],

        elements = root.getElementsByTagName(tag);

    for (var i = 0, len = elements.length; i < len; ++i) {

        // 根据自定义函数返回值判断节点的属性

        if ( method(elements[i]) ) {

            nodes[nodes.length] = elements[i];

            if (apply) {

                apply(elements[i]);

            }

        }

    }

    return nodes;

},OK,今天就先到这里。

相关推荐