Javascript 将数组添加到多维数组或对象中
我正在将Javascript 将数组添加到多维数组或对象中,javascript,Javascript,我正在将wysiwyg生成的内容解析到React中的目录小部件中 到目前为止,我正在遍历这些头并将它们添加到一个数组中 如何将它们全部放入一个多维数组或对象中(最好的方法是什么),使其看起来更像: h1-1 h2-1 h3-1 h1-2 h2-2 h3-2 h1-3 h2-3 h3-3 然后我可以在UI中用有序列表呈现它 const str=“h1-1h2-1h3-1somethingh1-2h2-2h3-2”; 常
wysiwyg
生成的内容解析到React中的目录小部件中
到目前为止,我正在遍历这些头并将它们添加到一个数组中
如何将它们全部放入一个多维数组或对象中(最好的方法是什么),使其看起来更像:
h1-1
h2-1
h3-1
h1-2
h2-2
h3-2
h1-3
h2-3
h3-3
然后我可以在UI中用有序列表呈现它
const str=“h1-1h2-1h3-1somethingh1-2h2-2h3-2”;
常量模式h1=/(.*)/g;
常数模式h2=/(.*)/g;
常量模式h3=/(.*)/g;
设h1s=[];
设h2s=[];
设h3s=[];
让match1,match2,match3;
while(matchh1=patternh1.exec(str))
h1s.推送(匹配H1[1])
while(matchh2=patternh2.exec(str))
h2s.推压(匹配H2[1])
while(match3=patternh3.exec(str))
h3s.push(匹配h3[1])
控制台日志(h1s)
控制台日志(h2s)
console.log(h3s)
您可以简单地收集所有h*
,然后对它们进行迭代以构建一个树:
使用ES6(我从您使用的const
和let
推断这是可以的)
const str=`
h1-1
h2-1
h3-1
某物
h1-2
h2-2
h3-2
`
常数模式h=/(.*)/g;
设hs=[];
让我们配对;
while(match=patternh.exec(str))
推送({lev:match[1],text:match[2]})
控制台日志(hs)
//使用以下格式构造树:[{value:…,子项:[{value:…,子项:[…]},…]},]
const add=(res、lev、what)=>{
如果(lev==0){
res.push({value:what,children:[]});
}否则{
添加(res[res.length-1]。children,lev-1,what);
}
}
//从空列表开始,使用上述方法将找到的所有hs减少到树中
常量树=hs.reduce((res,{lev,text})=>{
添加(res,lev-1,文本);
返回res;
}, []);
控制台日志(树);
但是,由于html标题本身不是树状结构(我猜这是您的用例),因此这仅在某些假设下有效,例如,除非上面有一个
,上面有一个
,否则您不能有
。它还将假定较低级别的标头始终属于紧接较高级别的最新标头
如果要进一步使用树结构,例如呈现TOC的代表性有序列表,可以执行以下操作:
// function to render a bunch of <li>s
const renderLIs = children => children.map(child => `<li>${renderOL(child)}</li>`).join('');
// function to render an <ol> from a tree node
const renderOL = tree => tree.children.length > 0 ? `<ol>${tree.value}${renderLIs(tree.children)}</ol>` : tree.value;
// use a root node for the TOC
const toc = renderOL({ value: 'TOC', children: tree });
console.log(toc);
//用于呈现一组的函数
const renderLIs=children=>children.map(child=>` ${renderOL(child)} `).join(“”);
//函数从树节点渲染
const renderOL=tree=>tree.children.length>0`${tree.value}${renderLIs(tree.children)}`:tree.value;
//使用TOC的根节点
const-toc=renderOL({value:'toc',children:tree});
控制台日志(toc);
希望有帮助。我不知道你的情况,但我讨厌用正则表达式解析HTML。相反,我认为让DOM处理这个问题是一个更好的主意:
const str=`h1-1
h3-1
h3-2
某物
h1-2
h2-2
h3-2`;
const wrapper=document.createElement('div');
wrapper.innerHTML=str.trim();
设tree=[];
设leaf=null;
for(wrapper.querySelectorAll(“h1,h2,h3,h4,h5,h6”)的常量节点){
const nodeLevel=parseInt(节点标记名[1]);
常数newLeaf={
级别:nodeLevel,
text:node.textContent,
儿童:[],
父:叶
};
while(leaf&&newLeaf.level您要做的是(文档大纲的变体),例如,从文档标题创建嵌套列表,尊重其层次结构
使用DOM和DOMParser API的浏览器的一个简单实现如下所示(放入HTML页面并在ES5中编码以便于测试):
文件大纲
//包装在文档(和主体)元素中的测试字符串
var str=“h1-1h2-1h3-1somethingh1-2h2-2h3-2”;
//用于遍历DOM并发出SAX startElement事件的util
函数emitSAXLikeEvents(节点、处理程序){
handler.startElement(节点)
对于(var i=0;i
我首先将您的片段解析为文档
,然后遍历它以创建类似SAX的startElement()
调用。在startElement()
函数中,根据最近创建的列表项(如果有)的排名检查标题元素的排名。然后在正确的层次结构级别追加一个新的列表项,并可能创建一个ol
元素作为它的容器。请注意,现有的算法不适用于从层次结构中的h1
跳到h3
,但可以轻松调整
如果您想在node.js上创建一个大纲/内容表,可以让代码运行服务器端,但需要一个像样的HTML解析库(可以说是node.js的DOMParser polyfill)。还有用于创建大纲的和包,尽管我还没有测试过。这些包据说还可以处理诸如标题之类的特殊情况
// function to render a bunch of <li>s
const renderLIs = children => children.map(child => `<li>${renderOL(child)}</li>`).join('');
// function to render an <ol> from a tree node
const renderOL = tree => tree.children.length > 0 ? `<ol>${tree.value}${renderLIs(tree.children)}</ol>` : tree.value;
// use a root node for the TOC
const toc = renderOL({ value: 'TOC', children: tree });
console.log(toc);
<!DOCTYPE html>
<html>
<head>
<title>Document outline</title>
</head>
<body>
<div id="outline"></div>
<script>
// test string wrapped in a document (and body) element
var str = "<html><body><h1>h1-1</h1><h2>h2-1</h2><h3>h3-1</h3><p>something</p><h1>h1-2</h1><h2>h2-2</h2><h3>h3-2</h3></body></html>";
// util for traversing a DOM and emit SAX startElement events
function emitSAXLikeEvents(node, handler) {
handler.startElement(node)
for (var i = 0; i < node.children.length; i++)
emitSAXLikeEvents(node.children.item(i), handler)
handler.endElement(node)
}
var outline = document.getElementById('outline')
var rank = 0
var context = outline
emitSAXLikeEvents(
(new DOMParser()).parseFromString(str, "text/html").body,
{
startElement: function(node) {
if (/h[1-6]/.test(node.localName)) {
var newRank = +node.localName.substr(1, 1)
// set context li node to append
while (newRank <= rank--)
context = context.parentNode.parentNode
rank = newRank
// create (if 1st li) or
// get (if 2nd or subsequent li) ol element
var ol
if (context.children.length > 0)
ol = context.children[0]
else {
ol = document.createElement('ol')
context.appendChild(ol)
}
// create and append li with text from
// heading element
var li = document.createElement('li')
li.appendChild(
document.createTextNode(node.innerText))
ol.appendChild(li)
context = li
}
},
endElement: function(node) {}
})
</script>
</body>
</html>