[英]Javascript: how to display certain amount of items from an array and display others on button click?
Implementation:执行:
I have an HTML page with items container:我有一个带有项目容器的 HTML 页面:
<section class="products">
<div class="container">
<h2 class="products-title">Some title</h2>
<div class="products-items"></div>
<button class="products-btn">Show more</button>
</div>
</section>
I have a data.js file with an array of items (16 items), here is an example:我有一个包含一组项目(16 个项目)的 data.js 文件,这是一个示例:
export const products = [
{
id: 0,
name: 'Product 1',
price: 23,
category: 'Category 1',
imgSrc: './images/product-photo.jpg',
},
];
I parsed data.js file using .map()
to populate 'products-items' div:我使用
.map()
解析 data.js 文件以填充“products-items”div:
const displayProducts = products => {
const productsContainer = document.querySelector('.products-items');
const newProducts = products.map(product => {
const {
id,
name,
price,
category,
imgSrc,
} = product;
return `
<div class="product-item" data-id="${id}">
<p>${name}</p>
<p>${price}</p>
<p>${category}</p>
<img src="${imgSrc}" alt="product photo">
</div>
`;
}).join('');
productsContainer.innerHTML = newProducts;
};
export default displayProducts;
In app.js I've imported products variable and displayProducts function.在 app.js 中,我导入了 products 变量和 displayProducts 函数。
If I pass products variable to display products like this displayProducts(products)
, it will show all 16 items.如果我传递 products 变量来显示像
displayProducts(products)
这样的displayProducts(products)
,它将显示所有 16 个项目。
Desired result:想要的结果:
What I need is to show only first 4 items and load 4 new items each time user clicks 'Show more' button.我需要的是每次用户单击“显示更多”按钮时只显示前 4 个项目并加载 4 个新项目。 In the end all 16 items should be displayed and 'Show more' button should be hidden.
最后应该显示所有 16 个项目,并且应该隐藏“显示更多”按钮。
When I had all 16 items as static data in HTML.当我将所有 16 个项目作为 HTML 中的静态数据时。 I used CSS to hide items by default:
.product-item {display: none}
我默认使用 CSS 隐藏项目:
.product-item {display: none}
Then I added class 'product-item--active' to first 4 items to display them by default: .product-item--active {display: block}
and used this functionality to add active class for remaining items on button click:然后我将类“product-item--active”添加到前 4 个项目以默认显示它们:
.product-item--active {display: block}
并使用此功能为按钮单击时的剩余项目添加活动类:
const showMoreBtn = document.querySelector('.products-btn');
let currentItems = 4;
showMoreBtn.addEventListener('click', e => {
const elementList = [
...document.querySelectorAll('.products-items .product-item'),
];
for (let i = currentItems; i < currentItems + 4; i++) {
if (elementList[i]) {
elementList[i].classList.add('product-item--active');
}
}
currentItems += 4;
// Hide load more button after all items were loaded
if (currentItems >= elementList.length) {
e.target.style.display = 'none';
}
});
Issue:问题:
But now, when items load dynamically, this functionality does not work.但是现在,当项目动态加载时,此功能不起作用。
I figured out how to display first 4 items using .slice()
:我想出了如何使用
.slice()
显示前 4 个项目:
let firstItems = products.slice(0, 4);
displayProducts(firstItems);
But, I can't figure out how to load new items on button click and hide it once all item displayed.但是,我无法弄清楚如何在单击按钮时加载新项目并在所有项目显示后隐藏它。
Update (Solved): I appreciate provided answers with good explanation and examples.
更新(已解决):我很欣赏提供了很好的解释和示例的答案。 Thank you.
谢谢你。 After examining them I have the following solution (in case if someone may find it useful).
在检查它们之后,我有以下解决方案(以防万一有人觉得它有用)。 Also, I removed redundant 'product-item--active' class from CSS, now there is no need to hide items by default:
此外,我从 CSS 中删除了多余的 'product-item--active' 类,现在默认情况下不需要隐藏项目:
import { products } from './data.js';
import displayProducts from './components/displayProducts.js';
const showMoreBtn = document.querySelector('.products-btn');
let currentItems = 0;
const displayNextFour = () => {
displayProducts(products.slice(currentItems, currentItems + 4));
// Display next 4 items until their amount exceeds
// the array length
if (!(currentItems + 4 > products.length)) {
currentItems += 4;
}
// Remove event listener from 'Show more' button and
// hide it after all items from the array are displayed
if (currentItems === products.length) {
showMoreBtn.removeEventListener('click', displayNextFour);
showMoreBtn.style.display = 'none';
}
};
displayNextFour();
showMoreBtn.addEventListener('click', displayNextFour);
Feel free to play with this minimal reproducable example using an array of 16 random strings for the content to display.随意使用这个最小的可重现示例,使用 16 个随机字符串的数组来显示内容。 It uses
insertAdjacentHTML
to append a block of 4 items on button click.它使用
insertAdjacentHTML
在按钮单击时附加 4 个项目的块。 That prevents overwriting all html on every click.这可以防止在每次点击时覆盖所有 html。 The click handler is assigned using Event Delegation .
单击处理程序是使用事件委托分配的。 If the number of items shown equals the available items, the button is disabled.
如果显示的项目数等于可用项目数,则该按钮被禁用。
A second idea may be to hide all but [ pageSize
] items and on button click unhide the next [ pageSize
] items.第二个想法可能是隐藏除 [
pageSize
] 项之外的所有项目,然后单击按钮取消隐藏下一个 [ pageSize
] 项。 See this stackblitz snippet .请参阅此 stackblitz 代码段。 That snippet is more generic: it enables a variable amount of items and setting a page size (number of items to show subsequently).
该片段更通用:它启用可变数量的项目并设置页面大小(随后显示的项目数)。 It requires no extra variables for tracking.
它不需要额外的跟踪变量。
initRandomStrExt(); document.addEventListener(`click`, handle); const fakeArray = [...Array(16)].map(v => String.getRandom(32)); // show first 4 items on page load addFourItems(fakeArray); function handle(evt) { if (evt.target.classList.contains(`products-btn`)) { return addFourItems(fakeArray); } } function addFourItems(fromArr) { // determine n of currently visible items const start = document.querySelectorAll(`.product-item`).length; // disable the button if all items will be visible after running this if (start === fromArr.length - 4) { document.querySelector(`.products-btn`).setAttribute(`disabled`, true); } // append 4 items of the array to the .product-items container document.querySelector(`.products-items`) .insertAdjacentHTML(`beforeend`, `<div>${fromArr.slice(start, start + 4) // ^ slice the next 4 items from the array .map((item, i) => `<div class="product-item">${i + 1 + start} - ${ item}</div>`).join(``)}</div>`); } // for demo, random string helper function initRandomStrExt() { if (String.getRandom) { return; } const characters = [...Array(26)] .map((x, i) => String.fromCharCode(i + 65)) .concat([...Array(26)].map((x, i) => String.fromCharCode(i + 97))) .concat([...Array(10)].map((x, i) => `${i}`)); const getCharacters = excludes => excludes && characters.filter(c => !~excludes.indexOf(c)) || characters; String.getRandom = (len = 12, excludes = []) => { const chars = getCharacters(excludes); return [...Array(len)] .map(() => chars[Math.floor(Math.random() * chars.length)]) .join(""); }; };
<section class="products"> <div class="container"> <h2 class="products-title">Some title</h2> <div class="products-items"></div> <p><button class="products-btn">Show more</button></p> </div>
You can create a global variable to keep track of which items should be dispalyed eg current_index
.您可以创建一个全局变量来跟踪应显示哪些项目,例如
current_index
。 Then create a function eg displayNextFour()
to display four items each time and update current_index
accordingly.然后创建一个函数,例如
displayNextFour()
每次显示四个项目并相应地更新current_index
。 Then on button click call displayNextFour()
function.然后在按钮上单击调用
displayNextFour()
函数。
let current_index = 0
const displayNextFour = () => {
displayProducts(products.slice(current_index, current_index+4));
//console.log(products.slice(current_index, current_index+4))
if(current_index + 4 <= products.length)
current_index+=4
}
(In displayProducts
create elements with product-item--active
class) (在
displayProducts
创建具有product-item--active
类的元素)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.