如何通过Javascript中的for of循环在DOM元素中包含函数(在数组对象中)



我试图在浏览器显示项目卡元素的倒数计时功能。我已经创建了包含键值对的对象数组。我有倒计时计时器功能包括在数组中,以及,我已经设法在一个项目卡显示定时器(附图),但努力找出我如何能显示定时器功能在所有项目卡。代码在这里:——

let products = {
data: [   
{ 
productName: "Orange",
catagory: "Fruits",
price: "5 / kg",
image: "orange1.jpg",
desc: "Freshly Picked Oranges",
timer: setInterval('updateTimer()', 1000)
},
{ 
productName: "Apple",
catagory: "Fruits",
price: "4 / kg",
image: "apple.jpg",
desc: "Freshly Picked Apple",
timer: setInterval('updateTimer()', 1000)
},
{ 
productName: "Pear",
catagory: "Fruits",
price: "6 / kg",
image: "pear1.jpg",
desc: "Freshly Picked Pear",
},
{ 
productName: "Banana",
catagory: "Fruits",
price: "4 / kg",
image: "banana1.jpg",
desc: "Freshly Picked Banana",
}
]
};

for (let i of products.data) {

let card = document.createElement("div");

card.classList.add("card", i.catagory, "hide");

let imgContainer = document.createElement("div");
imgContainer.classList.add("image-container");

let image = document.createElement("img");
image.setAttribute("src", i.image);
imgContainer.appendChild(image);
card.appendChild(imgContainer);

let container = document.createElement("div");
container.classList.add("container");

let name = document.createElement("h4");
name.classList.add("product-name");
name.innerText = i.productName.toUpperCase();
container.appendChild(name);

let desc = document.createElement("h5");
desc.innerText = i.desc;
container.appendChild(desc);

let price = document.createElement("h4");
price.innerText ="£" + i.price;
container.appendChild(price);

let timer = document.createElement("h3");
timer.setAttribute("id", "timer");
container.appendChild(timer);
card.appendChild(container);
document.getElementById("products").appendChild(card);

}

function updateTimer() {

future = Date.parse("apr 28, 2022 15:05:00");
now = new Date();
diff = future - now;
days = Math.floor(diff / (1000 * 60 * 60 * 24));
hours = Math.floor(diff / (1000 * 60 * 60));
mins = Math.floor(diff / (1000 * 60));
secs = Math.floor(diff / 1000);
d = days;
h = hours - days * 24;
m = mins - hours * 60;
s = secs - mins * 60;
document.getElementById("timer")
.innerHTML =
'<div>' + d + '<span>Days</span></div>' +
'<div>' + h + '<span>Hrs</span></div>' +
'<div>' + m + '<span>Mins</span></div>' +
'<div>' + s + '<span>Secs</span></div>';

if (diff < 0) {
clearInterval(setInterval('updateTimer()', 1000));
document.getElementById("timer")
innerHTML = `<h4 style="color:red" class="expired">sorry, this item has expired!</h4>`;
}
}
<body>
<div class="wraper">
<div id="search-container">
<input type="search" name="" id="search-input" placeholder="Search...">
<button id="search">Search</button>
</div>
<div id="buttons">
<button class="button-value" onclick="filterProduct('all')">All</button>
<button class="button-value" onclick="filterProduct('Fruits')">Fruits</button>
<button class="button-value" onclick="filterProduct('Vegetable')">Vegetable</button>
<button class="button-value" onclick="filterProduct('Dairy')">Dairy</button>
<button class="button-value" onclick="filterProduct('Bakery')">Bakery</button>
</div>
<div id="products"></div>
<!-- <div id="timer">0</div> -->


</div>

<script src="script.js"></script>
</body>

附加图片

问题是您只有一个Timer实例,但您需要多个独立实例,因为不同的产品可能有不同的报价。您正在从多个项目修改您的一个实例。你可以用类来做这类事情。这里有一个类Timer,它实现了你想要的。

它需要一个endDate和和HTMLElement,它连接,然后显示一个计时器。每次你需要一个计时器时,你只需要为它创建一个HTML元素和一个新的Timer实例。

class Timer {
#end;
#attached;
#interval;
/**
*
* @param {string} endTime Dates string (or other values that can be parsed to Date() constructor)
* @param {HTMLElement} attachTo HTML element this timer is attached to
*/
constructor(endTime, attachTo) {
this.#end = new Date(endTime);
this.#attached = attachTo;
}

start() {
// start timer interval
this.#interval = setInterval(() => this.updateTimer(), 1000);
}

stop() {
// stop the timer
clearInterval(this.#interval);
}

updateTimer() {
const diff = this.#end - new Date();

const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor(diff / (1000 * 60 * 60));
const mins = Math.floor(diff / (1000 * 60));
const secs = Math.floor(diff / 1000);

const d = days;
const h = hours - days * 24;
const m = mins - hours * 60;
const s = secs - mins * 60;

if(this.#attached){
this.#attached.innerHTML =
"<div>" +
d +
"<span>Days</span></div>" +
"<div>" +
h +
"<span>Hrs</span></div>" +
"<div>" +
m +
"<span>Mins</span></div>" +
"<div>" +
s +
"<span>Secs</span></div>";

if (diff < 0) {
this.stop();
this.#attached.innerHTML = `<h4 style="color:red" class="expired">sorry, this item has expired!</h4>`;
}
}
}
}

let products = {
data: [
{
productName: "Orange",
catagory: "Fruits",
price: "5 / kg",
image: "orange1.jpg",
desc: "Freshly Picked Oranges",
offerUntil: new Date(2022, 3, 28).toISOString()
},
{
productName: "Apple",
catagory: "Fruits",
price: "4 / kg",
image: "apple.jpg",
desc: "Freshly Picked Apple",
offerUntil: new Date(2022, 3, 25).toISOString()
},
{
productName: "Pear",
catagory: "Fruits",
price: "6 / kg",
image: "pear1.jpg",
desc: "Freshly Picked Pear",
},
{
productName: "Banana",
catagory: "Fruits",
price: "4 / kg",
image: "banana1.jpg",
desc: "Freshly Picked Banana",
},
],
};
// wait until HTML document is loadedn
window.addEventListener("DOMContentLoaded", e => {
for (let i of products.data) {
let card = document.createElement("div");

card.classList.add("card", i.catagory, "hide");

let imgContainer = document.createElement("div");

imgContainer.classList.add("image-container");

let image = document.createElement("img");
image.setAttribute("src", i.image);
imgContainer.appendChild(image);
card.appendChild(imgContainer);

let container = document.createElement("div");
container.classList.add("container");

let name = document.createElement("h4");
name.classList.add("product-name");
name.innerText = i.productName.toUpperCase();
container.appendChild(name);

let desc = document.createElement("h5");
desc.innerText = i.desc;
container.appendChild(desc);

let price = document.createElement("h4");
price.innerText = "£" + i.price;
container.appendChild(price);

// if this is an limited offer, attach a timer
if(i.offerUntil){
let timer = document.createElement("h3");
// create a new timer for given date and attach it to the newly created h3
i.timer = new Timer(i.offerUntil, timer);
i.timer.start();
container.appendChild(timer);
}
card.appendChild(container);
document.getElementById("products").appendChild(card);
}
})
<body>
<div class="wraper">
<div id="search-container">
<input type="search" name="" id="search-input" placeholder="Search...">
<button id="search">Search</button>
</div>
<div id="buttons">
<button class="button-value" onclick="filterProduct('all')">All</button>
<button class="button-value" onclick="filterProduct('Fruits')">Fruits</button>
<button class="button-value" onclick="filterProduct('Vegetable')">Vegetable</button>
<button class="button-value" onclick="filterProduct('Dairy')">Dairy</button>
<button class="button-value" onclick="filterProduct('Bakery')">Bakery</button>
</div>
<div id="products"></div>
<!-- <div id="timer">0</div> -->


</div>

<script src="script.js"></script>
</body>

您应该等到加载HTML文档之后再附加事件处理程序,就像使用DOMContentLoaded事件一样。

您还可以通过不使用innerHTML并且只计算一次时差来改进代码。然后,您可以将差值以天、小时等为单位存储为类属性,并对其进行递减,这将减少计算量。

请注意:我已经调整了你的输入,所以当报价不再可用时,每个产品都可以有一个日期作为ISO-8601字符串。

document.getElementById("timer")只返回它找到的第一个计时器。因为id应该是唯一的,应该没问题,但你想要创建多个,所以你可能应该使用可以重复的类。目前不能使用多个id和此getElementByID()方法。

所以,如果你有

<div class="timer" data-expiration="123456789">10 minutes</div>

或者类似的东西,然后你可以用。

来遍历所有的计时器。
document.querySelectorAll('.timer').forEach(timer => {
// update time.
});

根据评论中的问题更新。

简单的例子给一些想法。这并不完全是你的代码,因为我认为它会更容易理解没有所有其他的事情发生。希望这能让你了解如何查询元素,迭代它们,设置和清除间隔,以及设置和更新JS元素对象的属性。

// This demonstrates the use of `querySelectorAll` using a class on an element. This also shows how you can iterate the resulting list with `forEach`.
document.querySelectorAll('.timer').forEach(timer => {
// It is helpful to store the function so that we can pass it later to `setInterval`.
function updateTimer(timer) {
// Later we will store the current time as a property on our timer objects.
timer.currentTime -= 1;
timer.innerHTML = timer.currentTime;
// To clear a `setInterval`, you need to pass the ID. See https://developer.mozilla.org/en-US/docs/Web/API/setInterval. So, later we will store that on the timer object.
if (timer.currentTime === 0) {
clearTimeout(timer.updateIntervalID);
}
}
// We store the current time as mentioned above, so we can easily access it later.
// I didn't want to write date parsing, so this simply gets the attribute and counts down from that as an integer.
timer.currentTime = parseInt(timer.getAttribute('data-expiration'));
timer.innerHTML = timer.currentTime;
// See above. Here we set the ID from setInterval which is needed to clear it when we are done with the timer.
timer.updateIntervalID = setInterval(updateTimer, 1000, timer);
});
<!-- We cannot use ID the way it is in the code since only one element is allowed to have a specific ID. We can use class which can be used more than onece. -->
<div class="timer" data-expiration="500"></div>
<div class="timer" data-expiration="5"></div>

相关内容

  • 没有找到相关文章

最新更新