3 回答

TA貢獻1921條經驗 獲得超9個贊
使用Array.prototype.flatMap
可以大大降低轉換的復雜性 -
如果節點沒有值
data-element
,不包含節點;僅包括其子項的結果。
否則(通過歸納)該節點確實具有
data-element
值。將其包含element
在輸出中以及該節點的children
.
上面的編號點對應于下面的源評論 -
const root = document.querySelector('[data-element="from-here"]');
const toTree = ({ dataset = {}, children = [] }) =>
dataset.element === undefined // 1
? Array.from(children).flatMap(toTree) // 2
: [ { element: dataset.element // 3
, children: Array.from(children).flatMap(toTree)
}
]
console.log(toTree(root)[0])
<div data-element="from-here">
<div>skip me</div>
<div>
<div data-element="awesome">awesome text</div>
<div data-element="collect-me">
awesome text
<div data-element="also-me">
other text
<div class="but-not-me">...</div>
</div>
</div>
</div>
</div>
請注意,上面我們沒有使用querySelectorAll
,因為不需要額外的文檔查詢。然而,一些明顯的改進是 -
將樹的形狀定義為單獨的函數,
branch
為重復任務定義一個助手,
allToTree
const branch = (element = "", children = []) => // 1
({ element, children })
const allToTree = (nodes = []) => // 2
Array.from(nodes).flatMap(toTree)
toTree現在已經擺脫了復雜性。我們的意圖很明確,每個功能都易于編寫、測試和維護 -
const toTree = ({ dataset = {}, children = [] }) =>
dataset.element === undefined
? allToTree(children)
: [ branch(dataset.element, allToTree(children) ]

TA貢獻1865條經驗 獲得超7個贊
您可以使用Array.filter()它來過濾掉沒有屬性的元素data-element。
但為了包含包裝器 div,您可能data-element還需要添加屬性,如下所示。
const root = document.querySelector('[data-element="from-here"]');
function traverse(node) {
if (node.dataset.element) {
return {
element: node.dataset.element,
children: Array.from(node.querySelectorAll(':scope > div'))
.filter(child => {
return child.dataset.element || Array.from(child.children).some(grandChild => grandChild.dataset.element)
// If element has dataset or The child has some children with dataset attribute
})
.map(childNode => traverse(childNode)),
};
} else if (Array.from(node.children).some(child => child.dataset.element)) {
return Array.from(node.querySelectorAll(':scope > div')).filter(child => child.dataset.element).map(childNode => traverse(childNode))
}
}
console.log(traverse(root));
<div data-element="from-here">
<div>skip me</div>
<div>
<div data-element="awesome">awesome text</div>
<div data-element="collect-me">
awesome text
<div data-element="also-me">
other text
<div class="but-not-me">...</div>
</div>
</div>
</div>
</div>

TA貢獻1802條經驗 獲得超6個贊
為什么不使用 usingnode.querySelectorAll(':scope [data-element]')
來代替呢?這將覆蓋具有該屬性的所有元素,而不僅僅是第一層子元素。
這是一個小提琴: https: //jsfiddle.net/cp21ykng/2/或者我錯過了什么?
- 3 回答
- 0 關注
- 175 瀏覽
添加回答
舉報