【问题标题】:Vue - Using localStorage to hold a theme not working as expectedVue - 使用 localStorage 保存主题未按预期工作
【发布时间】:2021-10-30 06:57:00
【问题描述】:

这个问题让我在开发 Vue 网站时感到困惑一段时间,我无法通过其他线程解决我的特定错误。 这个想法应该很简单,有一个在“light”和“dark”之间切换值的开关,并将类绑定到该值。

<template>
  <div id="app" :class='themeValue'>
    <!-- Switch component from Buefy UI !-->
    <b-switch size='is-large' type='is-dark' v-model='theme'></b-switch>
    <!-- Other components !-->
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      theme: localStorage.getItem('theme') || false
    }
  },
  watch: {
    theme: function() {
      localStorage.setItem('theme', this.theme)
    }
  },
  computed: {
    themeValue: function() {
      return this.theme ? 'light' : 'dark'
    }
  }
}
</script>

<style lang="scss">
@import './_variables.scss';

.dark {
  color: $light;
  background-color: $background;
}

.light {
  color: $dark;
  background-color: $lightbackground;
}
</style>

我已经尝试了上述一百万种不同的变体,包括使用mounted() 设置this.theme、将所有逻辑保存在外部组件中以及使用$emit 等。

预期的行为是默认为深色主题,除非 localStorage 拥有“主题”的值,在这种情况下默认为该主题。开关组件应始终匹配主题的状态(即,如果保存为浅色主题,则开关应默认为true)。

上述代码的行为是始终默认为浅色主题,开关默认为false。这两个不同步(theme === true 时应用浅色主题),第一次按下开关不会更改主题但会自动更改为true,随后的按下工作正常(true 应用 .light 类, false 适用.dark)

编辑:localStorage 将真/假值存储为字符串。我认为你可以用 JSON.parse 做一个很好的实现,但我最终只使用了 mountedif (localStorage.getItem('theme') === 'true') 并且它工作正常。不用说,我真的很生气,这花了 4 个小时。

【问题讨论】:

    标签: javascript vue.js buefy


    【解决方案1】:

    好的,这就是我如何让它在本地工作,我切换了 or 语句并将属性名称更改为主题。

    <template>
      <div id="app" :class='themeValue'>
        <!-- Switch component from Buefy UI !-->
        <button size='is-large' type='is-dark' @click='themes = !themes'>klik</button>
        <!-- Other components !-->
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      data() {
        return {
          themes: false || localStorage.getItem('theme')
        }
      },
      watch: {
        theme: function() {
          localStorage.setItem('theme', this.theme)
        }
      },
      computed: {
        themeValue: function() {
          return this.themes ? 'light' : 'dark'
        }
      }
    }
    </script>
    
    <style lang="scss">
    
    
    .dark {
      color: white;
      background-color: black;
    }
    
    .light {
      color: black;
      background-color: white;
    }
    </style>
    

    所以我建议你将手表函数的名称更改为 updateTheme 之类的名称,并在你的数据属性中切换条件语句,然后它应该可以工作:)

    【讨论】:

    • 不幸的是,更改为button 过于简化了问题,因为它使b-switch 元素处于正确的配置中是设计的关键。正如我之前所说,开关正确执行其逻辑,应用程序只是没有正确加载其初始状态。也就是说,我将开关更改为具有@input='updateTheme' :value='theme' 并将watch 属性替换为updateTheme () { this.theme=!this.theme; localStorage.setItem('theme', this.theme) } 方法作为您的实现,它仍然默认为浅色主题=/
    • 好的,所以您可以将@input 更改为@input="theme = !theme",然后让您的观察者关注主题的变化并像updateTheme () { localStorage.setItem('theme', this.theme) } 那样更新您的本地存储。如果您将默认设置为 false,则默认设置为暗。
    • 这仍然无法在我的机器上运行,但我发现了这个错误。我将编辑原始帖子。谢谢你帮助好心的陌生人!
    • 哦,呵呵,当然是把它存储为字符串哈哈哈。完全没有注意到,很好,你设法找到了:)