Я был бы признателен за помощь в итеративном создании нижележащего div на основе количества элементов в словаре Javascript.
<div class = "container" style = "padding-bottom: 10px;">
<div class = "dropdown" style = "padding: 10px;">
<a href = "#">TOP 3 PS5 HEADSETS<i class = "fa fa-chevron-down"></i>
</a>
<ul>
<div id = "links">
<center>
<p>3: ↓ INSERT TITLE FOR STEELSERIES ↓</p>
</center>
<div class = "product">
<img src = "img/products/h-steelseries.png">
<a class = "link" href = "INSERT LINK HERE">Read More</a>
</div>
<center>
<p>3: ↓ INSERT TITLE FOR OTHER↓</p>
</center>
<div class = "product">
<img src = "img/products/h-other.png">
<a class = "link" href = "INSERT LINK HERE">Read More</a>
</div>
</div>
</ul>
</div>
</div>
Ниже находится файл read.js, содержащий элементы, для которых я хочу сгенерировать "продукт" класса div.
Я действительно хотел бы помочь с этим.
var prod_obj = {
"headphone_products" : {
"title": "Steelseries",
"IMAGE": "h-steelseries.png",
"HREF" : "steelseries.html"
},
"other_products" : {
"title": "Other product",
"IMAGE": "h-other.png",
"HREF" : "other.html"
}
};
Я просмотрел другие ответы и не смог найти пример словаря объектов, который использовался для автоматического создания div. Я намереваюсь использовать это для перечисления элементов на веб-сайте и хотел бы добавить объекты в словарь, чтобы они автоматически генерировали новый div для каждого объекта после выполнения сценария.
Спасибо за ваше время.
@ProfessorAbronsius извиняюсь, я бы хотел, чтобы результат был именно таким. Я бы хотел, чтобы этот div был сгенерирован для второго объекта в словаре и т. д.
Значит, это будет повторяться N раз? Если это так, то проблема заключается в идентификаторе links.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете просто перебрать объект и создать нужные узлы внутри цикла.
Вот более простая версия того же самого.
var prod_obj = {
"headphone_products": {
"title": "Steelseries",
},
"other_products": {
"title": "Other product",
}
};
for (let keys in prod_obj) {
const div = document.createElement("div");
div.innerText = prod_obj[keys].title
document.body.appendChild(div)
}Вы можете использовать циклы for-in и литералы шаблонов для достижения желаемого.
const prod_obj = {
"headphone_products": {
"title": "Steelseries",
"image": "h-steelseries.png",
"href": "steelseries.html"
},
"other_products": {
"title": "Other product",
"image": "h-other.png",
"href": "other.html"
}
};
const div = document.getElementById('insertHere');
for (let products_key in prod_obj) {
let {title, image, href} = prod_obj[products_key];
let html = `<p>Title: ${title}, Image: ${image}, href: ${href}</p>`;
div.insertAdjacentHTML('beforeend', html);
}<div id = "insertHere">
</div>То, что вы описываете, звучит как подходящий кандидат на шаблон, который, согласно документации по MDN, гласит:
The HTML Content Template () element is a mechanism for holding HTML that is not to be rendered immediately when a page is loaded but may be instantiated subsequently during runtime using JavaScript.
В следующем примере используется простой класс для загрузки нового экземпляра назначенного шаблона для каждого продукта, обнаруженного в исходных данных (то, что вы называете dictionary). После того, как шаблон загружен из теней, вы можете манипулировать содержимым по своему усмотрению. Если вы измените дизайн шаблона, вы измените дизайн окончательного макета. В исходном HTML нет элемента span, окружающего отдельные продукты, но способ, которым я написал загрузчик шаблонов (для конкретной работы), полностью клонирует дочерний элемент first, поэтому span не повлияет на макет, если специально для этого не задан стиль.
class TemplateLoader{
constructor( id ){
this.id=id;
return this.create();
};
gettemplate(){
return document.querySelector( 'template[ data-id = "'+this.id+'" ]' ) || false
};
clone(){
let tmpl=this.gettemplate();
return tmpl ? tmpl.content.firstElementChild.cloneNode( true ) : false;
};
gettarget(){
return document.querySelector( 'div[ id = "'+this.id+'" ]' ) || false;
};
create(){
let tmpl=this.clone();
if ( tmpl ){
let target=this.gettarget();
target.appendChild( tmpl );
return tmpl;
}
return false;
};
};
var prod_obj = {
'headphone_products' : {
'title': 'steelseries',
'image': 'h-steelseries.png',
'href' : 'steelseries.html'
},
'other_products' : {
'title': 'other product',
'image': 'h-other.png',
'href' : 'other.html'
},
'banana':{
'title':'curvy & yellow',
'image':'b-a-nana.png',
'href':'banana.html'
}
};
let id='links';
Object.keys( prod_obj ).forEach( cat => {
let data=prod_obj[ cat ];
let oTmpl=new TemplateLoader( id );
oTmpl.querySelector('center > p').textContent=data.title;
oTmpl.querySelector('div.product > img').src=['img/products',data.image].join('/');
oTmpl.querySelector('div.product > a.link').href=data.href;
});<!-- regular HTML -->
<div class='container'>
<div class='dropdown'>
<a href='#'>TOP 3 PS5 HEADSETS<i class='fa fa-chevron-down'></i></a>
<ul>
<div id='links'>
<!-- items will be populated here -->
</div>
</ul>
</div>
</div>
<!-- our template that will be used to generate new content within the above, regular HTML' -->
<template data-id='links'>
<span>
<center>
<p></p>
</center>
<div class='product'>
<img />
<a class='link'>Read More</a>
</div>
</span>
</template>Это великолепно. Приносим извинения за двойной пост - я отправил его со своего ноутбука, так как мой компьютер был с синим экраном, и я не смог найти этот пост. Это моя ошибка, но я случайно разместил не тот словарь - тот, что во втором посте, был правильным вложением.
В сообщении "other" структура данных сильно отличается от показанной здесь. Как эта структура должна использоваться с данным HTML здесь? В этих новых данных нет ссылок на изображения - теперь они избыточны?
В качестве примера я использовал ссылки на изображения. Мне это просто нужно, чтобы я мог добавлять дополнительные значения к объектам, если захочу в будущем.
Непонятно, как ваша новая структура данных должна работать с учетом вышеизложенного. Имеет ли значение, что существует несколько объектов верхнего уровня, каждый из которых содержит продукты - должен ли каждый продукт быть добавлен, как раньше, или существуют особые требования в отношении макета. Это четко не определено.
Между прочим, я только что заметил, что ваша разметка ошибочна ... Вы не можете вложить div в качестве прямого дочернего элемента элементов ul, но можно вложить элементы div в элемент li
Традиционный способ добавления содержимого в DOM на лету - использовать серию вызовов createElmenent и appendChild (что менее подвержено ошибкам, чем простая вставка строк HTML). И вы можете пройтись по ключам вашего объекта данных и извлечь детали вам нужно настроить ваши новые элементы DOM. Этот сценарий выполняет обе эти функции в функции updateDOM, которая вызывает функцию appendProductDetails один раз для каждого продукта.
Я изменил hrefs, чтобы создать функциональные (если произвольные) ссылки, и, конечно же, изображения не отображаются, потому что они не существуют на сервере StackOverflow. См. Комментарии в коде для дальнейшего объяснения.
const currentProds = getProductsToShow();
updateDOM(currentProds);
function updateDOM(prod_obj) {
// Identifies parent div
const linksDiv = document.getElementById("links");
// Clears parent div
linksDiv.innerHTML = "";
// Loops through productName (keys) in prod_obj
const productNames = Object.keys(prod_obj);
for (let productName of productNames) {
// Gets details (inner object) for each product
const details_obj = prod_obj[productName];
// Creates, configures, and appends new elements for each product
appendProductDetails(linksDiv, details_obj);
}
}
function appendProductDetails(parentElement, detailsObject) {
const
// Gets local copies of values via "destructuring"
{ title, image, href } = detailsObject,
path = "img/products/", // Defines path to images
// Creates elements to add to the DOM
productDiv = document.createElement("div"),
titleP = document.createElement("p"),
img = document.createElement("img"),
anchor = document.createElement("a");
// Configures newly created elements
productDiv.classList.add("product");
titleP.textContent = title;
img.src = path + image;
img.alt = image;
anchor.classList.add("link");
anchor.href = href;
anchor.textContent = "Read More";
// Puts children into productDiv
productDiv.appendChild(titleP);
productDiv.appendChild(img);
productDiv.appendChild(anchor);
// Attaches everything to the DOM
parentElement.appendChild(productDiv);
}
// Provides demo data
function getProductsToShow() {
const productsObj = {
"headphone_products": {
"title": "Steelseries",
"image": "h-steelseries.png", // In img/products/
"href": "https://stackoverflow.com"
},
"other_products": {
"title": "Other product",
"image": "h-other.png",
"href": "https://eloquentjavascript.net/"
}
};
return productsObj;
}.container{ width: 250px; text-align: center; }
.dropdown > a{ text-decoration: none; }
p{ margin: -0.1rem 0; font-size: 1.2rem; }
.product{ padding: 0.5rem ; }
.link{ margin-left: 1rem; }<div class = "container">
<div class = "dropdown">
<a href = "#">PS5 HEADSETS</a>
<div id = "links"></div>
</div>
</div>(Более современный подход заключался бы в многократном клонировании содержимого элемента template и использовании элементов slot для вставки соответствующих сведений о продукте в каждый новый экземпляр.)
Это все, что есть в HTML - он не будет повторяться, и вы просто хотите заполнить его значениями в данных json?