我正在实现一个类似于 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>
我能够创建解析后的 HTML 的 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 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 " ";
case 38: return "&";
case 60: return "<";
case 62: return ">";
case 173: return "­";
}
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/