У меня есть статический веб-сайт-портфолио без базы данных, я хочу посчитать «нет». товаров на одной странице и отображать их на другой.
Щас я это придумал
<script>
const elements = document.querySelectorAll('.product');
const count = elements.length;
document.getElementById("Count_exec_chair").innerHTML = count;
</script>
Но это работает только на одной странице. Я хочу посчитать товары на трех разных страницах и отобразить их на четвертой.
(Контекст: это веб-сайт небольшой мебельной компании, они добавили 15-20 товаров из 4 категорий вручную в разделы с помощью
и
Теперь они хотят, чтобы я написал код, чтобы каждый раз, когда кто-то добавлял товар, счетчик в меню увеличивался.)
Получив значение, сохраните его в localStorage
и на другой странице, которой это значение нужно, извлеките его. Кроме того, не используйте innerHTML
для хранения строк, в которых нет HTML. Вместо этого используйте .textContent
.
Как вы размещаете свои продукты на странице из базы данных? или используя продукты, хранящиеся в объекте JS?
но в моем сценарии люди сначала посещают страницу счетчика показов, а затем переходят на страницу с элементами
Вам понадобится какая-то форма хранения данных на стороне сервера.
Плохим, но довольно простым решением было бы разместить на странице 4 сценарий, который извлекает и анализирует страницы 1, 2, 3 и подсчитывает элементы. Это плохо, потому что он будет срабатывать каждый раз, когда кто-то загружает страницу 4, а не каждый раз, когда обновляется инвентарь, но, возможно, это не так заметно, особенно если страницы 1,2,3 уже находятся в кеше браузера.
В ОП неясно, как пользователь выбирает <div>
и как отслеживать это <div>
, поэтому в приведенном мной примере <input type = "checkbox">
используется как средство выбора пользователем элемента.
// All of a <form>'s <fieldset>, <input>, and <output> into an array
const items = Array.from(document.forms[0].elements);
// Iterating through the array, return the index of selected items or nothing
const cnt = items.flatMap((item, index) => item.checked ? index : [])
На каждой странице есть <fieldset>
- (document.forms[0].elements[0]
) и четыре <input type = "checkbox">
- (document.forms[0].elements[1 - 4]
), а на последней странице также есть <output>
- (document.forms[0].elements[5]
).
Каждая страница имеет числовое значение, присвоенное переменной idx
от 0 до 3. Каждая страница также представлена как литерал объекта: {}
хранится в массиве, который хранится в виде строки внутри localStorage
. Каждый литерал объекта имеет два свойства:
{
selected: [1, 2, 3, 4] // index numbers of selected `<input>`
total: 4 // total of selected `<input>`
}
Каждый раз при загрузке страницы из localStorage
извлекается массив объектов, и <input>
проверяются в соответствии со свойством .selected
объекта (например, [2, 3]
<input>
2 и 3 проверяются). Каждый раз, когда <input>
отмечен (или снят), соответствующий индекс этого <input>
добавляется в массив объектов .selected
этой страницы.
Кроме того, <output>
на последней странице будет отображать общую сумму свойств total
каждого объекта каждый раз, когда он загружается или если пользователь выбирает (или отменяет выбор) <input>
.
localStorage
не работает в SO-фрагменте, поэтому перейдите сюда для рабочего примера.
const key = 'count';
function getCount(key) {
return JSON.parse(localStorage.getItem(key)) || [{}, {}, {}, {}];
}
function getSelected() {
const items = Array.from(document.forms[0].elements);
return items.flatMap((item, index) => (item.checked ? index : []));
}
function setSelected() {
const items = Array.from(document.forms[0].elements);
const counts = getCount(key);
counts[idx].selected.forEach((number) => (items[number].checked = true));
}
function addSelected() {
const counts = getCount(key);
const cnt = getSelected();
counts[idx].selected = cnt;
counts[idx].total = cnt.length;
localStorage.setItem(key, JSON.stringify(counts));
}
function totalSelected() {
const counts = getCount(key);
const total = counts.reduce((sum, page) => sum + page.total, 0);
document.forms[0].elements.grandTotal.value = total;
}
document.addEventListener('DOMContentLoaded', setSelected);
document.forms[0].addEventListener('change', addSelected);
:root {
font: 5vmin/1 'Segoe UI';
}
menu {
list-style: none;
padding: 0;
display: flex;
justify-content: space-evenly;
}
label {
display: flex;
align-items: center;
margin-bottom: 0.5rem;
}
[type='checkbox'] {
width: 1rem;
height: 1rem;
margin-left: 0.5rem;
}
<!DOCTYPE html>
<html>
<head>
<link rel = "stylesheet" href = "lib/style.css" />
</head>
<body>
<nav>
<menu>
<li><a href = "index.html">Page 1</a></li>
<li><a href = "page2.html">Page 2</a></li>
<li><a href = "page3.html">Page 3</a></li>
<li><a>Page 4</a></li>
</menu>
</nav>
<form>
<fieldset>
<label> Item 13 <input type = "checkbox" /> </label>
<label> Item 14 <input type = "checkbox" /> </label>
<label> Item 15 <input type = "checkbox" /> </label>
<label> Item 16 <input type = "checkbox" /> </label>
<label> Total: <output id = "grandTotal"></output> </label>
</fieldset>
</form>
<script>
const idx = 3;
</script>
<script src = "lib/script.js"></script>
<script>
document.addEventListener('DOMContentLoaded', totalSelected);
document.forms[0].addEventListener('change', totalSelected);
</script>
</body>
</html>
Если у вас нет доступа к базе данных или серверу, вы можете использовать fetch(). Например, если вы поместите это в консоль этой страницы, оно должно показать, сколько элементов имеет класс -link--channel-name
на странице вопросов о переполнении стека:
Примечание. Будьте осторожны при копировании и вставке кода в консоль. Убедитесь, что вы знаете, что делает каждая строка кода.
fetch('https://stackoverflow.com/')
.then(result => result.text())
.then(text => {
var match = text.match(/class=["'][^"']*-link--channel-name[^"']*["']/g);
if (match) console.info(`Matches found: ${match.length}`);
else console.info(`Matches found: 0`);
});
Я бы предоставил фрагмент, но fetch
может быть сложно. При попытке использовать фрагмент политика CORS переполнения стека остановила его работу.
Я также должен отметить, что fetch
будет работать только в том случае, если страница, к которой вы пытаетесь получить доступ, имеет класс, написанный в HTML. Этот метод не может обнаружить класс или элементы, добавленные после загрузки страницы. В этом случае, если я ищу класс s-link
(ссылки на вопросы), я не получаю совпадений.
Если fetch работает на вашем веб-сайте, вот что делает этот код:
// Send a fetch request to the disired url.
// If on your own domain, you might not have to use a full url.
fetch('https://stackoverflow.com/')
// Take the result of that request and retrieve the text from it (the HTML of the page).
.then(result => result.text())
.then(text => {
// Take the text and search for the class using a regular expression.
var match = text.match(/class=["'][^"']*-link--channel-name[^"']*["']/g);
// Do something with the result.
if (match) console.info(`Matches found: ${match.length}`);
else console.info(`Matches found: 0`);
});
Не используйте регулярные выражения для обработки HTML. Разберите HTML и используйте методы DOM.
Это лучшая идея. Я не сталкивался с этой проблемой, поэтому у меня не было лучшего способа анализа HTML. Я мог бы сказать, что использование регулярных выражений может повысить производительность, но это, конечно, не лучшее решение. Ты прав.
У меня смутное представление о том, что локальное хранилище может быть полезно, но оно не сработает, если кто-то посетит вторую страницу раньше первой.