[英]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 更改該變量中的內容?
使用正確的方法來收集元素/節點*對於 DOM 操作很重要。 較舊的方法.children
、 .getElementsByTagName()
、 .getElementsByName()
、 .getElementsByClassName()
等返回 DOM 對象的實時集合。 這意味着如果此集合(又名HTMLCollection ,又名NodeList )中的任何對象(即元素,即<div>
、 <span>
,即不是spans={}
)被修改或刪除,或者如果添加了新對象,則整體收藏會立即改變。 這使得許多遞歸方式變得不可能和隨機。
出於某種原因,MDN 將實時集合稱為 HTMLCollection 或 NodeList,但提到如果使用諸如.querySelectorAll()
類的方法,則 NodeList 不是“實時”的。 為什么不將它稱為“靜態”集合以將其與不同的行為區分開來我不知道,特別是如果實時收集更多地是常見問題的來源,例如您遇到的問題。
首先,請放棄原貼(從這里簡稱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
。 如果您不注意范圍, let
和const
很容易削弱您的代碼。
<template>
標簽復制 HTML 片段<template>
組件for
循環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: <input id='ct' type='number' min='1' max='10' value='1'> Books: <input id='bk' type='number' min='1' max='10' value='1'> Pages: <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.