javascript - 实现像 data-reactid 这样的系统

标签 javascript html

我正在实现一个类似于 data-reactid 的系统(从头开始)。像这样的东西:(与使用 data-reactid 的目的不完全相同):

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <div>
        <p></p>
        <p></p>
        <p></p>
    </div>
</body>
</html>

<!DOCTYPE html>
<html data-id="0">
    <head data-id="0.0">
        <title data-id="0.0.0"></title>
    </head>
    <body data-id="0.1">
        <div data-id="0.1.1">
            <p data-id="0.1.1.0"></p>
            <p data-id="0.1.1.1"></p>
            <p data-id="0.1.1.2"></p>
        </div>
    </body>
</html>

我能够创建解析后的 H​​TML 的 JSON 对象,但无法以更简单的方式执行我想做的事情,你能帮我吗?

function mapDOM(element, json) {
    var treeObject = {};

    // If string convert to document Node
    if (typeof element === "string") {
        if (window.DOMParser) {
              parser = new DOMParser();
              docNode = parser.parseFromString(element,"text/xml");
        } else { // Microsoft strikes again
              docNode = new ActiveXObject("Microsoft.XMLDOM");
              docNode.async = false;
              docNode.loadXML(element); 
        } 
        element = docNode.firstChild;
    }

    //Recursively loop through DOM elements and assign properties to object
    var li=lj=lk=-1;
    function treeHTML(element, object) {
        ++li;
        object["type"] = element.nodeName;
        var nodeList = element.childNodes;
        if (nodeList != null) {
            if (nodeList.length) {
                object["content"] = [];
                for (var i = 0; i < nodeList.length; i++) {
                    ++lj;
                    if (nodeList[i].nodeType == 3) {
                        object["content"].push(nodeList[i].nodeValue);
                    } else {
                        object["content"].push({});
                        treeHTML(nodeList[i], object["content"][object["content"].length -1]);
                    }
                    document.getElementsByTagName(nodeList[i])[i].setAttribute("data-reactid","0."+i+"."+li+"."+lj);
                }
            }
        }
        if (element.attributes != null) {
            if (element.attributes.length) {
                object["attributes"] = {};
                for (var i = 0; i < element.attributes.length; i++) {
                    object["attributes"][element.attributes[i].nodeName] = element.attributes[i].nodeValue;
                }
            }
        }
    }
    treeHTML(element, treeObject);

    return (json) ? JSON.stringify(treeObject) : treeObject;
}

最佳答案

像那样吗?

function processNode(node, id) {
    id = !id ? "0" : String(id);
    node.dataset.id = id;
    return {
        id: id,
        type: node.nodeName.toLowerCase(),
        content: processNodeList( node.childNodes, id + "." ),
        attributes: processAttributes( node.attributes )
    }
}

function processNodeList(nodes, prefix){
    prefix = !prefix ? "" : String(prefix);

    for(var out, i=0, j=0, len = (nodes && nodes.length)|0; i < len; ++i){
        var node = nodes[i], nt = node.nodeType;
        if(nt === 1){ //Element
            value = processNode(node, prefix + j++);
        }else if(nt === 3){ //Text-Node
            //especially &nbsp; should be kept, and not replaced on stringify
            var text = node.textContent.replace(/[\u00A0<>&\u00AD]/g, toHtmlEntity);

            /*
            //TODO: move that into a filter, applied when the Array is built
            //remove all-whitespace-nodes between two block-nodes like p,div,section,h1-h6
            if((i === 0 || i === nodes.length-1) && /^[\r\n\t ]*$/.test(text)){
                //remove whitespace at the beginning or the end of the node
                continue;
            }
            */

            //compact multiple spaces into a single one
            value = text.replace(/([\r\n\t ])+/g, "$1");
        }else{
            continue;
        }

        out || (out = []);
        out.push(value);
    }
    return out;
}

function processAttributes(attrs){
    for(var out, i = 0, len = (attrs && attrs.length)|0; i < len; ++i){
        var attr = attrs[i];
        if(attr.nodeName === "data-id") continue;
        out || (out = {});
        out[attr.nodeName] = attr.nodeValue;
    }
    return out;
}

function toHtmlEntity(c){
    switch(c.charCodeAt(0)){
        case 160: return "&nbsp;";
        case 38: return "&amp;";
        case 60: return "&lt;";
        case 62: return "&gt;";
        case 173: return "&shy;";
    }
    return c;
}

function mapDOM(element) {
    // If string convert to document Node
    if (typeof element === "string") {
        if (window.DOMParser) {
              parser = new DOMParser();
              docNode = parser.parseFromString(element,"text/xml");
        } else { // Microsoft strikes again
              docNode = new ActiveXObject("Microsoft.XMLDOM");
              docNode.async = false;
              docNode.loadXML(element); 
        }
        element = docNode.firstChild;
    }

    return processNode(element);
}


var tree = mapDOM(document.body);
console.log(JSON.stringify(tree, null, 4));

关于javascript - 实现像 data-reactid 这样的系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35242309/

相关文章:

html - 在 html 选择选项中使用 <strong> 或 <span>

html - 仅在ie6中菜单下方有一个空白区域

javascript - 想知道这段代码摘录是否可以代表事件监听器

javascript - AsyncStorage 和抽屉呈现始终为空

javascript - Chart.js 在我点击标签 3 次之前不显示数据

Javascript 倒计时从上午 8 点到晚上 9 点

java - 从一组 HTML 文件中提取表格内容的最佳方法是什么?

JavaScript 读取 IE 和 FireFox 中的单选按钮值

java - 将 xml 字符串传输到 org.w3c.dom.Document 时忽略 org.xml.sax.SAXParseExceptions?

javascript - 到达页面底部时发出警报 当我在顶部时发出警报