简体   繁体   中英

How to make a “Mark as Read” with localStorage?

I'm trying to figure out how to keep “Mark as Read” as “Mark as Unread” even after refreshing the page. Vice versa too. How do I save the data with localStorage? So far, this is my code for “Mark as Read”:

 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();">

I click the “Mark as Read” and it becomes “Mark as Unread.” But after refreshing the page, it goes back to “Mark as Read.” How do I avoid that?

In your scripts you'll need to change two things:

<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.log(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>

In order to manage the read/unread state of items using localStorage as your persistent data store, you'll need to serialize your (un)read state as some kind of string to store as a value in the storage area (because localStorage only stores string values), and then deserialize the value when you retrieve it. JSON is an accessible choice for the serialization format because it naturally represents many JavaScript data structures and is easy to parse / stringify .

Questions like these are always hard to demonstrate in a working code snippet because Stack Overflow's code snippet environment is sandboxed and prevents access to things like localStorage , so when you try to use those features, a runtime exception is thrown as a result of the lack of permissions. N.netheless...

Below I've provided a self-contained example of storing the read/unread state for a list of items using basic functional programming techniques to keep the code organized. This is just plain HTML + CSS + JavaScript and doesn't use any frameworks like React, etc. You can copy + paste the code into a local HTML file on your computer and then serve it using a local static file web server (eg with Deno or Python , etc.) to see it working. I've included verbose comments for you to explain what's happening at every step of the program.

If you want to examine the state of your localStorage as you test the demo, see the question How to view or edit 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>

You were really close. What you have left is to use the local storage. For that, replace your JavaScript by the code below:

// 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");
  }
}

编辑 angry-fast-upe615

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM