首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >性能:生成扁平化的父子ID列表

性能:生成扁平化的父子ID列表
EN

Stack Overflow用户
提问于 2014-04-19 05:48:26
回答 1查看 334关注 0票数 0

我正在寻找一种更好的方法来生成基于特定id-pattern的父子关系映射。

请求void 0 === cache[parent][child]会更快;预期的结果是:

代码语言:javascript
复制
    {
      uuid_1: {uuid_2: {}}
      uuid_2: {uuid_3: {}, uuid_4: {}}
      uuid_3: {}
      uuid_4: {}
    }

HTML结构:

代码语言:javascript
复制
    <html id="uuid-1">
        <body id="uuid-2">
            <somewhere>
                <whatever id="uuid-3" />
            </somewhere>
            <foo id="uuid-4" />
        </body>
    </html>

_fetch()

代码语言:javascript
复制
    <1> // register as init
        <2> // register as child of 1
            <3>
                <4 /> // register as child of 2
            </3>
            <5 /> // register as child of 2
        </2>
    </1>

解析~1300个元素(大型菜单结构)以查找我的~50个uuid。

使用jQuery尝试1:

代码语言:javascript
复制
_fetch: function(element, factoryName)
{
    var a = {}, l = 0, t = this, f = function(el, n)
    {
        if(!a[n]) a[n] = {};

        var e = $(el), test = $('[id^="uuid-"]', e);

        if(!test.length)
            return;

        e.children().each(function()
        {
            var u = $(this), id = u.attr('id'), q;

            // anonymous element: no class defined
            if(!(id && 'uuid-' === id.slice(0x00, 0x05)))
            {
                f(this, n); // continue with current name
                return;
            }

            l++;
            q = $.T.util.uuidFromId(id);
            $.T.__dict[q] = '#' + id;

            a[n][q] = {};
            // comment in/out
            f(this, q);
        });

    }

    f(element, factoryName);
    return a;
}

尝试使用黄色JS的2:

代码语言:javascript
复制
    ..., g = function(n, p)
    {
        var r = [];
        for(var d = (p || document).getElementsByTagName('*'), i = 0, l = d.length; i < l; i++)
            d[i].getAttribute(n) && r.push(d[i]);
        return r;
    },
f = function(el, n)
{
    var z = el.children.length, y = 0;
    if(!a[n]) a[n] = {};

    if(z && g('id', el)) for(; y < z; y++)
    {
        var u = el.children[y], id = u.getAttribute('id'), q;

        if(!(id && 'uuid-' === id.slice(0x00, 0x05)))
        {
            f(u, n);
            continue;
        }

        l++;
        $.T.__dict[q = $.T.util.uuidFromId(id)] = '#' + id;
        a[n][q] = {};

        // it's irrelevant to fetch the full html or a sequence by constructor
        //f(u, q);
    }
}

我的问题是:如何以更快的方式将DOM元素收集为平面表示;就像上面的映射一样?我目前的解决方案非常滞后。

OT:基于map的上下文x-对话:

代码语言:javascript
复制
    <baz><alice><bob><bobchild/></bob></alice><foo />

    alice._init:
       before init children of bob
         tell foo 'go away'
       before init bob                // context: no bob
         after init children of alice //          && alice without children
            after init baz            //          && baz not ready -> no hello
               tell baz 'hello'
EN

回答 1

Stack Overflow用户

发布于 2014-04-19 07:06:23

我仍然不太确定我是否知道你想要做什么,但这是我所知道的最快的方法来遍历DOM树并累积父/子信息,就像你正在做的那样,构建你想要的数据结构:

代码语言:javascript
复制
var treeWalkFast = (function() {
    // create closure for constants
    var skipTags = {"SCRIPT": true, "IFRAME": true, "OBJECT": true, 
        "EMBED": true, "STYLE": true, "LINK": true, "META": true};

    return function(parent, fn, allNodes) {
        var parents = [];
        var uuidParents = [];
        parents.push(parent);
        uuidParents.push(parent);
        var node = parent.firstChild, nextNode, lastParent;
        while (node && node != parent) {
            if (allNodes || node.nodeType === 1) {
                if (fn(node, parents, uuidParents) === false) {
                    return(false);
                }
            }
            // if it's an element &&
            //    has children &&
            //    has a tagname && is not in the skipTags list
            //  then, we can enumerate children
            if (node.nodeType === 1 && node.firstChild && !(node.tagName && skipTags[node.tagName])) {
                // going down one level, add this item to the parent array
                parents.push(node);
                if (node.id && node.id.substr(0, 5) === "uuid-") {
                    uuidParents.push(node);
                }
                node = node.firstChild;
            } else  if (node.nextSibling) {
                // node had no children so going to next sibling
                node = node.nextSibling;
            } else {
                // no child and no nextsibling
                // find parent that has a nextSibling
                while ((node = node.parentNode) != parent) {
                    lastParent = parents.pop();
                    if (lastParent === uuidParents[uuidParents.length - 1]) {
                        uuidParents.pop();
                    }
                    if (node.nextSibling) {
                        node = node.nextSibling;
                        break;
                    }
                }
            }
        }
    }
})();

var objects = {uuid_1: {}};
treeWalkFast(document.documentElement, function(node, parents, uuidParents) {
    if (node.id && node.id.substr(0, 5) === "uuid-") {
        var uuidParent = uuidParents[uuidParents.length - 1];
        if (!objects[uuidParent.id]) {
            objects[uuidParent.id] = {};
        }
        objects[uuidParent.id][node.id] = {};
        objects[node.id] = {};
    }
});

工作演示:http://jsfiddle.net/jfriend00/yzaJ6/

这是我为this answer编写的treeWalkFast()函数的改编。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23162930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档