根据 localStorage 布尔值在 if 条件下处理 addEventListener

handle addEventListener in if condition based on localStorage boolean value

我正在尝试根据 OS 级别 light/dark 模式切换主题。用户在使用网站时可能会更改系统设置。所以,我需要实时更新而不是页面刷新。所以,我正在使用 addEventListener 来获取系统当前的变化。 addEventListener 工作正常。但是,如果系统设置选项设置为 true,它应该可以工作。

我已将系统设置作为布尔选项存储在 localStorage 中。 如果为真,则唯一的 addEventListener 应该起作用。如果它是假的,它应该不起作用。 但是,我的问题是 addEventListener 在这两种情况下都有效。我的意思是,如果系统设置既不是 true 也不是 false,它就可以工作。我如何处理 addEventListener 应该基于 localStorage 值工作(如果系统设置设置为真)?

JsFiddle

JS

function defaultFunction() {
    localStorage.setItem('option', 'default');
  localStorage.setItem('systemOption', false);
}
defaultFunction();

function myFunction() {
  let getOption = localStorage.getItem('option');
  let themeDiv = document.getElementById('theme');
  
  if(localStorage.getItem('systemOption') == 'true') {
    let osTheme = window.matchMedia('(prefers-color-scheme: dark)');
    osTheme.addEventListener('change', event => {
      if(event.matches) {
        themeDiv.classList.add("dark");
        themeDiv.classList.remove("default");
      } else {
        themeDiv.classList.add("default");
        themeDiv.classList.remove("dark");
      }
    })
  } else {
    if(getOption == 'dark') {
      themeDiv.classList.add("dark");
      themeDiv.classList.remove("default");
    } else if(getOption == 'default') {
      themeDiv.classList.add("default");
      themeDiv.classList.remove("dark");
    }
  }
}
myFunction();

function setDark() {
    localStorage.setItem('option', 'dark');
  myFunction();
}

function setLight() {
    localStorage.setItem('option', 'default');
  myFunction();
}

function checkBox() {
    let cBox = document.getElementById('system');
  let sun = document.getElementById('sun');
  let moon = document.getElementById('moon');
  
  if(cBox.checked) {
    localStorage.setItem('systemOption', true);
    sun.classList.add('addOpacity');
    moon.classList.add('addOpacity');
  } else {
    localStorage.setItem('systemOption', false);
    sun.classList.remove('addOpacity');
    moon.classList.remove('addOpacity');
  }
  myFunction();
}

现在可以了。

<div id="theme">
  Testing based on User OS level light/dark theme
</div>
<div class="option">
  <span id="sun" class="lightCls" onclick="setLight();">Light</span>
  <span id="moon" class="darkCls" onclick="setDark();">Dark</span>
  <span>
    <input type="checkbox" id="system" onclick="checkBox();" />
    <label for="system">System Setttings</label>
  </span>
</div>

<style>
* {
  margin: 0;
  padding: 0;
}
#theme {
  width: 100%;
  height: 100vh;
}
.default {
  background: #ddd;
  color: #000;
}
.dark {
  background: #101010;
  color: #fff;
}
.option {
  position: absolute;
  right: 0;
  bottom: 0;
  background: #fff;
  border: 1px solid #ccc;
  padding: 3px;
}
.lightCls, .darkCls {
  padding: 2px;
  cursor: pointer;
}
.lightCls {
  background: #ddd;
  color: #000;
}
.darkCls {
  background: #101010;
  color: #fff;
}
.addOpacity {
  opacity: 0.2;
  pointer-events: none;
}
</style>

<script>
function defaultFunction() {
    localStorage.setItem('option', 'default');
  localStorage.setItem('systemOption', false);
}
defaultFunction();

function myFunction() {
  let getOption = localStorage.getItem('option');
  let themeDiv = document.getElementById('theme');
  
  if(localStorage.getItem('systemOption') == 'true') {
    let osTheme = window.matchMedia('(prefers-color-scheme: dark)');
    osTheme.addEventListener('change', event => {
      if(event.matches) {
        themeDiv.classList.add("dark");
        themeDiv.classList.remove("default");
      } else {
        themeDiv.classList.add("default");
        themeDiv.classList.remove("dark");
      }
    })
  } else {
    if(getOption == 'dark') {
      themeDiv.classList.add("dark");
      themeDiv.classList.remove("default");
    } else if(getOption == 'default') {
      themeDiv.classList.add("default");
      themeDiv.classList.remove("dark");
    }
  }
}
myFunction();

function setDark() {
    localStorage.setItem('option', 'dark');
  myFunction();
}

function setLight() {
    localStorage.setItem('option', 'default');
  myFunction();
}

function checkBox() {
    let cBox = document.getElementById('system');
  let sun = document.getElementById('sun');
  let moon = document.getElementById('moon');
  
  if(cBox.checked) {
    localStorage.setItem('systemOption', true);
    sun.classList.add('addOpacity');
    moon.classList.add('addOpacity');
  } else {
    localStorage.setItem('systemOption', false);
    sun.classList.remove('addOpacity');
    moon.classList.remove('addOpacity');
  }
  myFunction();
}

</script>



我认为问题在于您正在添加一个事件侦听器,但您从未将其删除,因此它始终在侦听该事件。

有条件地尝试 adding/removing 事件侦听器,如下所示

function changeListener(event) {
  if(event.matches) {
    themeDiv.classList.add("dark");
    themeDiv.classList.remove("default");
  } else {
    themeDiv.classList.add("default");
    themeDiv.classList.remove("dark");
  }
}


let osTheme = window.matchMedia('(prefers-color-scheme: dark)');
if(localStorage.getItem('systemOption') === 'true') {
    osTheme.addEventListener('change', changeListener);
} else {
    osTheme.removeEventListener('change', changeListener);
}

始终监听事件并通过检查 localStorage

有条件地应用主题
const osTheme = window.matchMedia('(prefers-color-scheme: dark)');
osTheme.addEventListener('change', event => {
    if(localStorage.getItem('systemOption') === 'true') {
        if(event.matches) {
            themeDiv.classList.add("dark");
            themeDiv.classList.remove("default");
        } else {
            themeDiv.classList.add("default");
            themeDiv.classList.remove("dark");
        }
    }
});