Я пытаюсь понять, как сохранить «Отметить как прочитанное» как «Отметить как непрочитанное» даже после обновления страницы. Наоборот тоже. Как сохранить данные с помощью localStorage? Пока что это мой код для «Пометить как прочитанное»:
function readunread() {
currentvalue = document.getElementById("readunread").value;
if (currentvalue == "Mark as Unread"){
document.getElementById("readunread").value = "Mark as Read";
} else{
document.getElementById("readunread").value = "Mark as Unread";
}
}
body {
background:black;
}
.button {
border: none;
color: white;
font-family: Corbel;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
background-color: black;
}
input[type=button] {
font-size: 20px;
font-family: Corbel;
text-decoration: none;
color: white;
border: none;
background: none;
cursor: pointer;
margin: 0;
padding: 0;
}
<input type = "button" value = "Mark as Read" id = "readunread" onclick = "readunread();">
Я нажимаю «Отметить как прочитанное», и оно становится «Отметить как непрочитанное». Но после обновления страницы она возвращается к «Отметить как прочитанное». Как этого избежать?
В ваших сценариях вам нужно будет изменить две вещи:
<script>
function readunread() {
currentvalue = document.getElementById("readunread").value;
if (currentvalue == "Mark as Unread") {
document.getElementById("readunread").value = "Mark as Read";
// 1. Update the localstorage
localStorage.setItem("readunread", "Mark as Read");
} else {
document.getElementById("readunread").value = "Mark as Unread";
// 1. Update the localstorage
localStorage.setItem("readunread", "Mark as Unread");
}
}
</script>
<input
type = "button"
value = "Mark as Read"
id = "readunread"
onclick = "readunread();"
/>
<script>
// 2. Get the value from the local storage
function loadInitialValue() {
const localValue = localStorage.getItem("readunread");
console.info(localValue);
if (localValue == "Mark as Unread") {
document.getElementById("readunread").value = "Mark as Unread";
} else {
document.getElementById("readunread").value = "Mark as Read";
}
}
loadInitialValue(); // Make sure to call the function
</script>
Спасибо за ответ. Однако… похоже, это не работает с моей стороны. Как мне именно вызвать «loadInitialValue()»? Сделать это так: <input type = "button" value = "Mark as Read" id = "readunread" onclick = "readunread();" onclick = "loadInitialValue();">
Или это как-то связано с setInterval?
Я отредактировал сообщение, чтобы иметь полностью рабочую версию.
Чтобы управлять прочитанным/непрочитанным состоянием элементов, используя localStorage
в качестве постоянного хранилища данных, вам необходимо сериализовать свое (не)прочитанное состояние как некую строку для хранения в качестве значения в области хранения (поскольку localStorage
хранит только строковые значения), а затем десериализовать значение при его извлечении. JSON является доступным выбором для формата сериализации, поскольку он естественным образом представляет многие структуры данных JavaScript и его легко анализировать / приводить в строки.
Подобные вопросы всегда трудно продемонстрировать в рабочем фрагменте кода, потому что среда фрагмента кода Stack Overflow изолирована и предотвращает доступ к таким вещам, как localStorage, поэтому, когда вы пытаетесь использовать эти функции, возникает исключение времени выполнения в результате отсутствие разрешений. Тем не менее...
Ниже я привел самодостаточный пример хранения прочитанного/непрочитанного состояния для списка элементов с использованием основных методов функционального программирования для организации кода. Это просто HTML + CSS + JavaScript и не использует никаких фреймворков, таких как React и т. д. Вы можете скопировать и вставить код в локальный файл HTML на своем компьютере, а затем использовать его с помощью локального веб-сервера статических файлов (например, с помощью Deno или Python и т. д.), чтобы увидеть, как это работает. Я включил подробные комментарии для вас, чтобы объяснить, что происходит на каждом этапе программы.
Если вы хотите проверить состояние вашего localStorage во время тестирования демо, см. вопрос Как просмотреть или отредактировать localStorage?.
<!doctype html>
<html lang = "en">
<head>
<meta charset = "utf-8" />
<meta name = "viewport" content = "width=device-width, initial-scale=1" />
<title>LocalStorage: read/unread items</title>
<style>
/* Just some styles for this example: styling is up to you */
* { box-sizing: border-box; }
body { font-family: sans-serif; }
.toggle-status {
font-size: 1rem;
padding: 0.25rem;
width: 8rem;
}
#list {
list-style: none;
padding: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
align-items: flex-start;
}
.item {
display: flex;
gap: 1rem;
align-items: center;
}
.item.read > .item-content { font-weight: normal; }
.item.unread > .item-content { font-weight: bold; }
</style>
<script type = "module">
// Get the state of all of the read/unread items from localStorage
// as an object:
function getStatusMap () {
try {
// Get the JSON value from local storage:
// if it doesn't exist, it will be null, so use a default value instead:
// a JSON string representing an empty object:
const storageValue = window.localStorage.getItem('read_status_map') ?? '{}';
// Parse the string value into an actual object:
const readStatusMap = JSON.parse(storageValue);
// Return the value if it's a plain object:
if (
typeof readStatusMap === 'object'
&& readStatusMap !== null
&& !Array.isArray(readStatusMap)
) return readStatusMap;
// Else throw an error because it was an invalid value:
throw new Error('Unepxected value');
}
catch (ex) {
// Catch any exception which might have occurred.
// You can handle it however you want (or just ignore it).
// For example, you could print it
// to the console error stream to view it:
console.error(ex);
// Return an empty object as the default:
return {};
}
}
// Update the localStorage state of all the read/unread items:
function setStatusMap (statusMap) {
const json = JSON.stringify(statusMap);
const storageValue = window.localStorage.setItem('read_status_map', json);
}
// Update the read/unread status for a single item:
function updateStatus (statusMap, listItemElement, isReadStatus) {
const button = listItemElement.querySelector(':scope > button.toggle-status');
// Depending on the current status, update the action button's text
// to describe the next (opposite) action:
button.textContent = `Mark as ${isReadStatus ? 'unread' : 'read'}`;
// Get the ID from the list item's data attribute:
const {id} = listItemElement.dataset;
// Get the state object of the current item from the status map object,
// OR create one if it doesn't exist yet. You can store other information
// about each item here, but — in this example — only the ID (string)
// and read status (boolean) properties are stored:
const status = statusMap[id] ??= {id, isRead: false};
// Update the read status of the item:
status.isRead = isReadStatus;
// Update the whole state in localStorage:
setStatusMap(statusMap);
// Optional: update the list item's read/unread class.
// This can help with applying CSS styles to the items:
if (isReadStatus) {
listItemElement.classList.add('read');
listItemElement.classList.remove('unread');
}
else {
listItemElement.classList.remove('read');
listItemElement.classList.add('unread');
}
}
// A convenience function which toggles between read/unread for an item:
function toggleStatus (statusMap, listItemElement) {
// Get the ID from the list item's data attribute:
const {id} = listItemElement.dataset;
// Get the current status (or false by default if it doesn't exist yet):
let isRead = statusMap[id]?.isRead ?? false;
// Toggle it to the opposite state:
isRead = !isRead;
// Update it:
updateStatus(statusMap, listItemElement, isRead);
}
// Now, using the functions above together:
function main () {
// Get the initial read/unread status map:
const statusMap = getStatusMap();
// Get an array of the item elements:
const listItemElements = [...document.querySelectorAll('#list > li.item')];
for (const listItemElement of listItemElements) {
// Get the ID from the list item's data attribute:
const {id} = listItemElement.dataset;
// Set the initial read status for each item to what was found
// in localStorage, or if nothing was found then set to false by default:
const initialStatus = statusMap[id]?.isRead ?? false;
updateStatus(statusMap, listItemElement, initialStatus);
const button = listItemElement.querySelector(':scope > button.toggle-status');
// Set an action for each item's toggle button: when it is clicked,
// toggle the status for that item. Formally, this is called "binding an
// event listener callback to the button's click event":
button.addEventListener(
'click',
() => toggleStatus(statusMap, listItemElement),
);
}
}
// Invoke the main function:
main()
</script>
</head>
<body>
<!--
A list of items, each with:
- a unique ID
- a toggle button,
- and some text content
-->
<ul id = "list">
<li class = "item" data-id = "cc9e88ce-3ed4-443a-84fc-fa7147baa025">
<button class = "toggle-status">Mark as read</button>
<div class = "item-content">First item content</div>
</li>
<li class = "item" data-id = "23a9204c-905f-48db-9f6a-deb3c8f82916">
<button class = "toggle-status">Mark as read</button>
<div class = "item-content">Second item content</div>
</li>
<li class = "item" data-id = "18b47e4c-635f-49c0-924e-b9088538d08a">
<button class = "toggle-status">Mark as read</button>
<div class = "item-content">Third item content</div>
</li>
<li class = "item" data-id = "ed2aacca-64f0-409d-8c1b-d1bdcb7c6058">
<button class = "toggle-status">Mark as read</button>
<div class = "item-content">Fourth item content</div>
</li>
<li class = "item" data-id = "0fce307b-656a-4102-9dc9-5e5be17b068d">
<button class = "toggle-status">Mark as read</button>
<div class = "item-content">Fifth item content</div>
</li>
<!-- ...etc. -->
</ul>
</body>
</html>
Вы были очень близки. Вам осталось использовать локальное хранилище. Для этого замените свой JavaScript кодом ниже:
// On Load
const readUnreadButton = document.getElementById("readunread");
document.getElementById("readunread").value =
localStorage.getItem("readunread") || readUnreadButton.value;
// On Click
function readunread() {
const readUnreadButton = document.getElementById("readunread");
currentvalue = readUnreadButton.value;
if (currentvalue == "Mark as Unread") {
readUnreadButton.value = "Mark as Read";
localStorage.setItem("readunread", "Mark as Read");
} else {
readUnreadButton.value = "Mark as Unread";
localStorage.setItem("readunread", "Mark as Unread");
}
}
Вы пытались использовать setItem и getItem? developer.mozilla.org/en-US/docs/Web/API/Window/localStorage