【问题标题】:How can I remember which class was toggled after page reload using local storage我如何记住在使用本地存储重新加载页面后切换了哪个类
【发布时间】:2021-10-28 03:09:39
【问题描述】:

我有一个具有相同类的项目列表,每个项目都有一个按钮,单击时可以切换离线类。我使用 for 循环和 forEach 循环使用事件侦听器“单击”遍历列表,然后检查项目类列表是否包含“离线”。如果它包含离线,则按钮 innerText 更改为离线以及样式。现在的问题是当我重新加载页面时,一切都会重置。我试过使用本地存储,但它会将离线类恢复到每个项目。

let statusBtn = document.getElementsByClassName("statusBtn");
let status = localStorage.getItem("status");

// Array.prototype.forEach.call(statusBtn, (Btn) => {
//   Btn.addEventListener("click", () => {
//     Btn.classList.toggle("offline");
//     if (Btn.classList.contains("offline") == true) {
//       Btn.innerText = "Offline";
//       localStorage.setItem("status", "offline");
//     } else {
//       Btn.innerText = "Online";
//       Btn.classList.remove("offline");
//       localStorage.setItem("status", "online");
//     }
//   });
// });

for (let i = 0; i < statusBtn.length; i++) {
  statusBtn[i].addEventListener("click", () => {
    statusBtn[i].classList.toggle("offline");
    if (statusBtn[i].classList.contains("offline") == true) {
      statusBtn[i].innerText = "Offline";
      localStorage.setItem("status", "offline");
    } else {
      statusBtn[i].innerText = "Online";
      statusBtn[i].classList.remove("offline");
      localStorage.setItem("status", "online");
    }
  });
}

for (let i = 0; i < statusBtn.length; i++) {
  if (localStorage.getItem("status") === "offline") {
    statusBtn[i].innerText = "Offline";
    statusBtn[i].classList.add("offline");
  }
}
.offline {
  background: #f00;
  color: #fff;
}
<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
</head>

<body>
  <div class="container">
    <div id="inputContainer">
      <input type="text" name="search" id="myInput" placeholder="  Type The Store Name Here" />
    </div>
    <ul id="myUL">
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 935/932
            <button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Anthos: Gauteng, Krugersdorp
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 873<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Athlone: Westerncape, Athlone
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1067<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Arbour-Crossing: KwaZulu-Natal, Amazimtoti
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1052<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Amanzimtoti - KZN Amanzimtoti
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 927/950<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Arcadia: Gauteng, Arcadia, Arcadia
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 889/891<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Atteridgeville: Gauteng, Atteridgeville
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1106<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Avon-Wood: Western Cape, Avonwood
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1159<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Ballito: KwaZulu-Natal, Ballito
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 937<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Beaufort West: Western Cape, Beaufort West
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 968/969<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Bellville Mall: Western Cape, Kuilsriver
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 892<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Benmore: No Collection
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 828/829<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> BirchAcres Mall: Gauteng, Thembisa
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 881<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> BlueDowns: Westerncape, BlueDowns
        </a>
      </li>
    </ul>
  </div>
  <script src="popup.js"></script>
</body>

</html>

【问题讨论】:

  • 1.请发布 minimal reproducible example - 尽可能少的代码。 2. 代表。不建议为容器中多个相同类型的元素添加事件监听器。将监听器添加到容器中。
  • 每次使用相同的键 "status" 会覆盖该值,这是需要的吗?
  • 您是否知道相同的 localStorage key 即。 status 正在用于所有按钮?
  • 是的,但是如何将 localStorage 键分配给特定的数组项而不是全部
  • @SandileS 您只能接受一个答案。请确保您接受对您帮助最大的那个。

标签: javascript html css local-storage


【解决方案1】:

这是一个大大简化的版本

这将使调试和修复任何错误变得更容易。

注意我已经注释掉了 sn-p 的 localStorage。 不建议循环获取状态。

我存储一个数组并使用 JSON.parse 读取和 JSON.stringify 写入

const ul = document.getElementById("myUL");
const input = document.getElementById("myInput");
const statusBtn = document.querySelectorAll(".statusBtn");
let status = ["online","offline"]  // JSON.parse(localStorage.getItem("status"));


function myFunction() {
  // Declare variables
  let input, filter, ul, li, a, i, txtValue;
  filter = input.value.toUpperCase();
  lia = ul.querySelectorAll("li a");
  // Loop through all list items, and hide those who don't match the search query
  lia.forEach(a => {
    const txtValue = a.textContent.toUpperCase();
    a.closest("li")
      .classList
      .toggle("hide", input && txtValue.indexOf(filter) === -1)
  })
}
document.getElementById("myInput").addEventListener("keyup", myFunction);

// When the user scrolls the page, execute myFunction
window.onscroll = function() {
  stickySearch();
};
// Get the navbar
let search = document.getElementById("inputContainer");
// Get the offset position of the navbar
let sticky = search.offsetTop;
// Add the sticky class to the navbar when you reach its scroll position. Remove "sticky" when you leave the scroll position
function stickySearch() {
  search.classList.toggle("sticky", window.pageYOffset >= sticky);
}


ul.addEventListener("click", (e) => {
  const tgt = e.target
  tgt.classList.toggle("offline");
  const isOnline = tgt.classList.contains("online")
  tgt.textContent = isOnline ? "Offline" : "Online";
  status[+tgt.dataset.idx]=isOnline ? "offline" : "online";
  // localStorage.setItem("status", JSON.stringify(status));

});


statusBtn.forEach((btn,i) => {
  const isOnline = status[i] === "online"; 
  btn.textContent = isOnline ? "Online" : "Offline";
  btn.dataset.idx=i;
  btn.classList.add(isOnline ? "online" : "offline");
})
@import url("https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@700&display=swap");
body {
  padding: 0;
  scroll-behavior: smooth;
  background: #18202d;
}

.container {
  width: 300px;
  font-family: "Roboto Condensed", sans-serif;
  max-height: 200px;
  scrollbar-width: thin;
}

input {
  height: 25px;
  width: 95%;
  margin-right: 5%;
  border: 1px solid #18202d;
  border-radius: 0.1rem;
  display: flex;
  justify-content: center;
  margin: 0 auto;
}

#myUL {
  list-style-type: none;
  padding: 0;
  margin: 0;
  max-height: 100px;
  z-index: -1;
}

#myUL li {
  border-top: solid 1px #ccc;
  z-index: -1;
}

#myUL li:nth-child(even) {
  background: #2b3546c2;
}

#myUL li a {
  padding: 5px;
  text-decoration: none;
  font-size: 13px;
  color: #fff;
  display: block;
}

#inputContainer {
  padding: 2%;
  background: #18202d;
}

#myUL .ext {
  color: #ccc;
  padding-bottom: 1%;
}

::-webkit-scrollbar {
  display: none !important;
}

.sticky {
  position: fixed;
  top: 0;
  width: 92%;
}

.backToTop {
  color: #fff;
  z-index: 1;
}

.float-end {
  float: right;
  border-radius: 0.1rem;
  border: 1px solid #ccc;
  cursor: pointer;
}

.statusBtn {
  background: #0f0;
}

.offline {
  background: #f00;
  color: #fff;
}

.hide {
  display: none
}
<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
</head>

<body>
  <div class="container">
    <div id="inputContainer">
      <input type="text" name="search" id="myInput" placeholder="  Type The Store Name Here" />
    </div>
    <ul id="myUL">
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 935/932
            <button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Anthos: Gauteng, Krugersdorp
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 873<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Athlone: Westerncape, Athlone
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1067<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Arbour-Crossing: KwaZulu-Natal, Amazimtoti
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1052<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Amanzimtoti - KZN Amanzimtoti
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 927/950<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Arcadia: Gauteng, Arcadia, Arcadia
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 889/891<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Atteridgeville: Gauteng, Atteridgeville
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1106<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Avon-Wood: Western Cape, Avonwood
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1159<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Ballito: KwaZulu-Natal, Ballito
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 937<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Beaufort West: Western Cape, Beaufort West
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 968/969<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Bellville Mall: Western Cape, Kuilsriver
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 892<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Benmore: No Collection
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 828/829<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> BirchAcres Mall: Gauteng, Thembisa
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 881<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> BlueDowns: Westerncape, BlueDowns
        </a>
      </li>
    </ul>
  </div>
  <script src="popup.js"></script>
</body>

</html>

【讨论】:

    【解决方案2】:

    您可以简单地添加一个索引并存储每个按钮的状态,您可以将每个按钮视为一个人的名字,因为如果您想可靠地存储每个人的详细信息,则没有两个人应该有相同的名字

        for (let i = 0; i < statusBtn.length; i++) {
            statusBtn[i].addEventListener("click", () => {
                statusBtn[i].classList.toggle("offline")
    
                if (statusBtn[i].classList.contains("offline") == true) {
                    statusBtn[i].innerText = "Offline";
                    localStorage.setItem("status_of_"+ i , "offline");
                } else {
                    statusBtn[i].innerText = "Online";
                    statusBtn[i].classList.remove("offline");
                    localStorage.setItem("status_of_"+i , "online");
                }
            });
        }
    
        //LOAD STATE FROM STORAGE
        for (let i = 0; i < statusBtn.length; i++) {
            if (localStorage.getItem("status_of_"+i) === "offline") {
                statusBtn[i].innerText = "Offline";
                statusBtn[i].classList.add("offline");
            }
        }
    
    

    【讨论】:

    • 非常感谢,这就像一个魅力
    【解决方案3】:

    请注意,使用 localStorage 函数 setItem(key, value) getItem(key) removeItem(key) 您只能存储字符串类型的键和值对。
    如果您的项目因存储的密钥过多而增长,但 localStorage 仍然足够好,另一种方法可以将数组中的值解析为 statusArray .join(' ') 到一个字符串,然后通过 statusValue.split(' ') 获取它们。

    for (let i = 0; i < statusBtn.length; i++) {
        statusBtn[i].addEventListener("click", () => {
            statusBtn[i].classList.toggle("offline")
            let statusArray = localStorage.getItem("status").split(' ');
            if (statusBtn[i].classList.contains("offline") == true) {
                status[i].innerText = "Offline";
                statusArray[i] = "offline";
            } else {
                statusBtn[i].innerText = "Online";
                statusBtn[i].classList.remove("offline");
                statusArray[i] = "online";
            }
            localStorage.setItem("status", statusArray.join(' '));
        });
    }
    
    //LOAD STATE FROM STORAGE
    let statusArray = localStorage.getItem("status").split(' ');
    for (let i = 0; i < statusBtn.length; i++) {
        if (statusArray[i] === "offline") {
            statusBtn[i].innerText = "Offline";
            statusBtn[i].classList.add("offline");
        }
    }
    

    【讨论】:

    • 不要忘记在第一行添加“i”,其中 i 必须小于 statusBtn.length
    • @SandileS :D 谢谢。你知道 json(javascript 对象表示法)吗?您在这里不需要它(只有两种状态,因此您可以使用布尔值或符号 0 和 1),但它是用于将对象解析为字符串和反向的官方格式,因此您可以一般使用它:w3schools
    • 是的,我知道 JSON,但我对 javascript 还是很陌生。我曾考虑过使用它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    相关资源
    最近更新 更多