簡體   English   中英

遞歸 Function 從 DOM Object 創建 DOM 樹字符串

[英]Recursive Function to Create DOM Tree String from DOM Object

我目前正在努力構建一個 function,它應該從解析 HTML5 ( node-html5-parser ) 中獲取輸入 object,我需要處理所有標簽和子標簽,它們的內容為 output xml 的字符串。我遇到的問題是如何獲得遞歸 function(或任何函數)以正確維護 HTML5 標簽順序並輸出內容。

例子:

<div><span>My Content</span></div>

使用 node-html5-parser,我在解析時得到以下信息:

rootElem {
    childNodes: [
        {
            tagName: 'div',
            childNodes: [
                {
                    tagName: 'span',
                    childNodes: [
                        {
                             rawText: 'My Content'
                        }
                    ],
                }
            ]
        }
    ]
}

我認為可以使用簡單的 DFS 遞歸算法來構建字符串,但我無法使其正常工作。

const DOMRootObj = parse(this.htmlStr);

const processedData = this.processContent(DOMRootObj);
 processContent(root: any): string {
    if (root && !root.childNodes.length) {
      return root.rawText;
    } else {
      for (const childNode of root.childNodes) {

        const str = this.processContent(childNode);

        const { tagName } = childNode;

        if (tagName) {
          this.outputStr += `<${tagName}>${str}</${tagName}>`;
        }

      }
    }


  }

從這個 HTML 由 parse() function 解析:(對象如上)

<div><span>My Content</span></div>

這最終輸出:

<span>undefined</span><div>undefined</div>

但它應該是 output:

<div><span>My Content</span></div>

不確定您期望哪種 XML 格式,但遞歸調用並不難實現:

 function toString(node, name="root") { let tag = typeof name === "string"? name: node.tagName; return tag? `<${tag}>${(node.childNodes||[]).map(toString).join``}</${tag}>`: (node.rawText || ""); } // Sample: let rootElem = { childNodes: [{ tagName: 'div', childNodes: [{ tagName: 'span', childNodes: [{ rawText: 'My Content' }], }] }] }; console.log(toString(rootElem, "root"));

我在瀏覽器中遇到了幾天類似的問題。 我想遍歷 dom 樹並在節點上使用給定參數執行 function。 在我的情況下,我想重新分配元素 ID(如果有)。 這就是為什么 function 被命名為 nodeinit。 無論如何

             function nodeinit(node,dataset){console.log(node);}  

             function shadowWalker(node, nodeinit, dataset) {
                nodeinit(node, dataset);
                if (node) {
                    console.log(node.id);
                    if (node.childNodes.length > 0) {
                        node = node.firstChild; //needed to init while loop
                        while (node) {
                            shadowWalker(node, nodeinit, dataset);
                            node = node.nextSibling;
                        }
                    }
                }
            }

因此,它與要啟動的節點一起調用。 Nodeinit 是 function 和 dataset 是 nodeinit function 的參數 object (某種預設)。 您可以通過尋找橫向 dom 樹在這里找到一些類似的答案。 只是作為一個想法或起點。

未經修飾的代碼,但你可以得到ideia。 您只需重復該模式即可添加更多屬性,例如 onclick 和 tabindex。 盡管我不認為將所有內容都放在生成器上是個好主意(您可能會忘記正在生成的內容)。

fillHeaderCurrenciesList = () => {
    // Generated structure example
    // <div
    //     id='currency-1'
    //     class='currency currency--hoverable'
    //     onclick='selectMainCurrency(this.id)'
    // >
    //     <div class='currency__name'>Bitcoin</div>

    //     <div class='currency__icon'>
    //         <img src='assets/img/icon-coin.svg' alt='LG Bank' />

    //         <img src='assets/img/icon-btc.svg' alt='LG Bank' />
    //     </div>

    //     <div class='currency__balance'>
    //         <span class='currency__title'>Balance</span>

    //         <div class='currency__value'>
    //             <span>Exemplo1 | R$ 234.342.367,90</span>
    //         </div>
    //     </div>
    // </div>;

    let currenciesList = document.getElementById('currencies-list');

    for (let i = 0; i < currencyData.length; i++) {
        const currency = currencyData[i];

        let currencyTree = {
            tagName: 'div',

            id: `currency-${i}`,
            class: ['currency', 'currency--hoverable'],
            onClick: function () {
                selectMainCurrency(this, 'currencies-main-currency');
            },

            onKeyDown: function () {
                keyDownEnter(
                    selectMainCurrency(this, 'currencies-main-currency')
                );
            },

            tabIndex: '0',

            children: [
                {
                    tagName: 'div',
                    class: ['currency__name'],
                    text: currency.name,
                },

                {
                    tagName: 'div',
                    class: ['currency__icon'],

                    children: [
                        {
                            tagName: 'img',
                            src: currency.icon.src,
                            alt: currency.icon.alt,
                        },

                        {
                            tagName: 'img',
                            src: currency.iconName.src,
                            alt: currency.iconName.alt,
                        },
                    ],
                },

                {
                    tagName: 'div',
                    class: ['currency__balance'],

                    children: [
                        {
                            tagName: 'span',
                            class: ['currency__title'],
                            text: 'Balance',
                        },

                        {
                            tagName: 'div',
                            class: ['currency__value'],

                            children: [
                                {
                                    tagName: 'span',
                                    text: currency.balance,
                                },
                            ],
                        },
                    ],
                },
            ],
        };

        currenciesList.appendChild(DOMListItemGenerator(currencyTree));
    }
};

const currencyData = [
    {
        name: 'bitcoin',
        icon: {
            src: 'assets/img/icon-coin.svg',
            alt: 'LG Bank',
        },
        iconName: {
            src: 'assets/img/icon-btc.svg',
            alt: 'LG Bank',
        },
        quotation: '',
        balance: 'Exemplo1bitcoin | R$ 234.342.367,90',
    },
    {
        name: 'ethereum',
        icon: {
            src: 'assets/img/icon-coin.svg',
            alt: 'LG Bank',
        },
        iconName: {
            src: 'assets/img/icon-btc.svg',
            alt: 'LG Bank',
        },
        quotation: '',
        balance: 'Exemplo2ethereum | R$ 234.342.367,90',
    },
    {
        name: 'ethereum',
        icon: {
            src: 'assets/img/icon-coin.svg',
            alt: 'LG Bank',
        },
        iconName: {
            src: 'assets/img/icon-btc.svg',
            alt: 'LG Bank',
        },
        quotation: '',
        balance: 'Exemplo2ethereum | R$ 234.342.367,90',
    },
    {
        name: 'ethereum',
        icon: {
            src: 'assets/img/icon-coin.svg',
            alt: 'LG Bank',
        },
        iconName: {
            src: 'assets/img/icon-btc.svg',
            alt: 'LG Bank',
        },
        quotation: '',
        balance: 'Exemplo2ethereum | R$ 234.342.367,90',
    },
    {
        name: 'teste',
        icon: {
            src: 'assets/img/icon-coin.svg',
            alt: 'LG Bank',
        },
        iconName: {
            src: 'assets/img/icon-btc.svg',
            alt: 'LG Bank',
        },
        quotation: '',
        balance: 'Exemplo3teste | R$ 234.342.367,90',
    },
];

fillHeaderCurrenciesList();


DOMListItemGenerator = (inputTree) => {
    let tree = Object.entries(inputTree);
    let item;
    let output;

    for (let i = 0; i < tree.length; i++) {
        const branch = tree[i];

        if (branch[0] === 'tagName') {
            output = document.createElement(branch[1]);
        }

        if (branch[0] === 'id') {
            output.setAttribute('id', branch[1]);
        }

        if (branch[0] === 'tabIndex') {
            output.setAttribute('tabindex', branch[1]);
        }

        if (branch[0] === 'class') {
            for (const classItem of branch[1]) {
                output.classList.add(classItem);
            }
        }

        if (branch[0] === 'src') {
            output.src = branch[1];
        }

        if (branch[0] === 'alt') {
            output.alt = branch[1];
        }

        if (branch[0] === 'text') {
            output.textContent = branch[1];
        }

        if (branch[0] === 'onClick') {
            output.onclick = branch[1];
        }

        if (branch[0] === 'onKeyDown') {
            output.onkeydown = branch[1];
        }

        if (branch[0] === 'children' && branch[1].length > 0) {
            for (let j = 0; j < branch[1].length; j++) {
                const children = branch[1][j];
                item = DOMListItemGenerator(children);
                output.appendChild(item);
            }
        }
    }

    return output;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM