如何将DOM的子树转换为DocumentFragment?

时间:2017-03-28 13:48:24

标签: javascript dom

我正在尝试“保留”DOM的子树以供以后使用,并根据一些用户操作(我最初创建并使用DocumentFragment操作然后附加到DOM的子树)重新出现,但我不知道我想在DOM中的某处附加并隐藏它,因为对它的进一步操作(在我的情况下很重)操作较慢并且会引起布局重排和进一步的性能影响。

是否有跨浏览器方式(我关心的IE11 +)将一些DOM子树转换回DocumentFragment?没有通过搜索SO或文档找到任何东西。

谢谢

1 个答案:

答案 0 :(得分:0)

我建议将您感兴趣的节点保存在数组中。 DocumentFragment更方便,而不像NodeList或HTMLCollection那样令人讨厌。

将“东西”转换为documentFragments的小实用程序。

function fragmentFlush(state){
    if(state.text){
        state.fragment.appendChild(document.createTextNode(state.text));
        state.text = "";
    }
    return state.fragment;
}

function fragmentIterate(state, value){
    if( value instanceof Node ){
        fragmentFlush(state).appendChild(value);
    }else if(Array.isArray(value)){
        value.reduce(fragmentIterate, state);
    }else if(value === Object(value)){
        fragmentIterate(state, Array.from(value));
    }else if(value != null){
        state.text += value;
    }
    return state;
}

function fragment(value){
    return fragmentFlush(fragmentIterate({
        text: "",
        fragment: document.createDocumentFragment()
    }, value));
}

“things”因为它遍历任何(非循环)arraylike结构以找到您传递的节点并从中构建(展平的)documentFragment。 (原始值转换为TextNodes,忽略nullundefined

var setA = [/*...*/];

var frag = fragment([
    "setA: ", setA,
    condition? "some more text": null,  //null values are ignred
    "setB: ", someNode.children,
    //that's why I made this traverse recursively
    //so that I can "concat" lists like the following line
    //without having to actually concat them
    "setC: ", [setA, anotherSet, /* moreNodes */, andAnotherSet]
]);

node.appendChild(frag);

再次注意,不处理循环引用!

关于这三个函数,我刚刚从我的一个库中提取了这个函数。您可能希望将其放入模块中,只导出fragment或将其包装到IIFE中。