簡體   English   中英

需要幫助正確迭代 DOM 並替換元素 - Javascript

[英]Need help iterating over DOM properly and replacing elements - Javascript

在此先感謝您的幫助! 我正在嘗試執行一些遞歸跨度標記“replaceWith”操作,用一個 div 和 3 個子跨度替換跨度。 我的子對象(包含要替換的跨度)在替換第一個跨度時以某種方式更新(導致我的對象每次增長 2)時遇到了一個大問題,所以我想我會嘗試制作對象不變,然后冷凍或密封。 我不確定這是否是正確的方法,但我不是一個足夠好的 javascript 程序員知道。 無論如何,我以這種方式獲取我的跨度對象:

let el = document.getElementById("container");
let nodes = el.children[0];
Object.seal(nodes);//THIS SEALS/FREEZES JUST FINE
let spans = {};//TRIED WITH AND W/O THIS JUST TO MAKE SURE THE OBJECT WAS CREATED
const spans = nodes.children;
console.log('type of spans: '+typeof spans);//RETURNS object
console.log('spans length: '+spans.length);//RETURNS spans length: 3
console.log('spans: '+JSON.stringify(spans));//RETURNS spans: {"0":{},"1":{},"2":{}}
Object.seal(spans);///RETURNS Uncaught TypeError: Cannot Seal

HTML很簡單:

<body>
    <button id="fractalize">Fractalize</button>
    <br/>
    <br/>
    <div id="container">
        <div class="sierpinski">
            <span></span>
            <span></span>
            <span></span>
        </div>
    </div>
</body>

spans 作為一個對象返回,但在使用 Object.freeze 或 Object.seal 時它一直失敗! 我需要知道是否有人可以告訴我我做錯了什么.. spans 對象在我看來與 nodes 對象沒有任何不同,並且 nodes 對象凍結/密封就好了。 如果我可以凍結這些對象,那么我的計划是為替換執行以下操作:

for( let key in spans ) {
  if( spans.hasOwnProperty(key) ) {
    console.log(key + " -> " + JSON.stringify(spans[key]));
    let nDiv = document.createElement("div");
    nDiv.className="sierpinski";
    nDiv.innerHTML="<span></span><span></span><span></span>";
    spans[key].replaceWith(nDiv.cloneNode(true));
    nDiv.remove();
  }
}

感謝您的任何見解!

編輯為了洞察力,這就是我想要的;

<body>
    <button id="fractalize">Fractalize</button>
    <br/>
    <br/>
    <div id="container">
        <div class="sierpinski">
            <div class="sierpinski">
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
            </div>
            <div class="sierpinski">
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
            </div>
            <div class="sierpinski">
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <div class="sierpinski">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
            </div>
        </div>
    </div>
</body>

這就是我目前得到的;

<body>
    <button id="fractalize">Fractalize</button>
    <br/>
    <br/>
    <div id="container">
        <div class="sierpinski">
            <div class="sierpinski">
                <span></span>
                <div class="sierpinski">
                    <span></span>
                    <div class="sierpinski">
                        <span></span>
                        <div class="sierpinski">
                            <span></span>
                            <span></span>
                            <span></span>
                        </div>
                        <span></span>
                    </div>
                    <span></span>
                </div>
                <span></span>
            </div>
            <span></span>
            <span></span>
        </div>
    </div>
</body>

那么我是否添加/刪除類或其他東西以便代碼迭代具有某種錨點? 我只是不明白如何聲明一個變量等於某些子元素並且不會保持永久。 如何在不重新定義變量的情況下更改 DOM 更改該變量中的內容?

實時和“靜態” HTMLCollections / NodeLists

使用正確的方法來收集元素/節點*對於 DOM 操作很重要。 較舊的方法.children.getElementsByTagName().getElementsByName().getElementsByClassName()等返回 DOM 對象的實時集合 這意味着如果此集合(又名HTMLCollection ,又名NodeList )中的任何對象(即元素,即<div><span> ,即不是spans={} )被修改或刪除,或者如果添加了新對象,則整體收藏會立即改變 這使得許多遞歸方式變得不可能和隨機。

出於某種原因,MDN 將實時集合稱為 HTMLCollection 或 NodeList,但提到如果使用諸如.querySelectorAll()類的方法,則 NodeList 不是“實時”的。 為什么不將它稱為“靜態”集合以將其與不同的行為區分開來我不知道,特別是如果實時收集更多地是常見問題的來源,例如您遇到的問題。


DOM 對象(蘋果)和對象字面量(橙色)

首先,請放棄原貼(從這里簡稱OP)代碼。 特別是這部分:

Object.seal(nodes);//THIS SEALS/FREEZES JUST FINE
let spans = {};//TRIED WITH AND W/O THIS JUST TO MAKE SURE THE OBJECT WAS CREATED
const spans = nodes.children;
console.log('type of spans: '+typeof spans);//RETURNS object
console.log('spans length: '+spans.length);//RETURNS spans length: 3
console.log('spans: '+JSON.stringify(spans));//RETURNS spans: {"0":{},"1":{},"2":{}}
Object.seal(spans);///RETURNS Uncaught TypeError: Cannot Seal

spans不是<span></span><span></span><span></span>spans{"0":{},"1":{},"2":{}} 前者是一個HTMLCollection (或NodeList ),后者是一個Object Literal ,apples and oranges。 Object.seal()是原型屬性的方法。 此外,在您有更多經驗之前,請使用var 如果您不注意范圍, letconst很容易削弱您的代碼。


演示大綱

  1. <template>標簽復制 HTML 片段
  2. 為每次迭代克隆並附加<template>組件
  3. 使用 3 for循環
  4. 使用 HTMLFormControlsCollection 進行用戶輸入
  5. let聲明某些值

演示

注意:布局保持接近 OP,除了:

  • <template>的使用

  • 目標元素隱藏在<template>

  • 沒有費心創建 4 個嵌套級別,有 3 個應該就足夠了

  • 不打算嘗試謝爾賓斯基三角形所以改變了類來代表書籍

演示中評論的詳細信息

演示

 // Refer to HTMLFormControlsCollection var UI = document.forms.ui.elements; // Register click event to button UI.btn.addEventListener('click', generate); function generate() { // Reference to #main var main = document.getElementById('main'); // Refer to Template Tag var library = document.querySelector('.library'); var lib = library.content.cloneNode(true); /* Refer to HTMLFormControlsCollection || The user data is collected in a live collection || Note that these values are outside of the loops */ var ct = UI.ct.value; var bk = UI.bk.value; var pg = UI.pg.value; /* let declaration limits it's value to the block. || var limit's its value to the function. || In this example let declares the initial value || inside each FOR loop. If a var was used then it || would be declared outside of the loop. == || Recursion is nested 2 levels deep and on each || iteration, a component from template.library || is cloned and appended. */ for (let l = 0; l < ct; l++) { // Reference lib .category let cat = lib.querySelector('.category'); // Create a shallow clone of .category (sec) var sec = cat.cloneNode(false); // Append sec it to #main main.appendChild(sec); for (let b = 0; b < bk; b++) { // Reference lib .category .book let book = lib.querySelector('.book'); // Create shallow clone of .book (pub) var pub = book.cloneNode(false); // Append it to .category (sec) sec.appendChild(pub); for (let p = 0; p < pg; p++) { // Reference lib .category .book .page let page = lib.querySelector('.page'); // Create a deep clone of.page (copy) var copy = page.cloneNode(true); // Append it to .book (pub) pub.appendChild(copy); } // Continue to add a cloned copy to pub [pg] times } // Continue to add cloned pub to sec [bk] times } // Continue to add cloned sec to #main [ct] times }
 input { font: inherit; width: 4ch; } button { font: inherit; width: 10ch; } #main { border: 6px dotted grey; display: table } .category { background: rgba(0, 0, 0, .6); display: table-row } .category::before { content: '\\1f4da'; } .book { border: 3px solid red; display: table-cell } .book::before { content: '\\1f4d8'; } .page { border: 1px solid gold; display: inline-block; } .page::before { content: '\\1f4c3'; }
 <!doctype html> <html> <head> </head> <body> <form id='ui'> <label>Categories:&nbsp; <input id='ct' type='number' min='1' max='10' value='1'> &nbsp;Books:&nbsp; <input id='bk' type='number' min='1' max='10' value='1'> &nbsp;Pages:&nbsp; <input id='pg' type='number' min='1' max='10' value='1'> </label> <button id="btn" type='button'>Generate</button> <br/> <br/> <!-- Refer to Template Tag--> <template class='library'> <section class='category'> <article class='book'> <span class='page'></span> </article> </section> </template> <main id="main"> </main> </form> </body> </html>

參考

暫無
暫無

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

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