【问题标题】:darkmode with vuex and save in localstorage使用 vuex 的暗模式并保存在本地存储中
【发布时间】:2021-01-20 09:56:14
【问题描述】:

我有一个 chrome 错误告诉我写入操作失败:计算属性“isDark”是只读的。

我的突变在 locastorage 中创建了一个 DarkMode 键,我还创建了一个商店来检查是否存在于 localestorage 中的 DarkMode

它可以工作,但是如果我刷新页面,突变会被反转,例如,如果在 localestorage 中,darkMode 为真,如果我点击切换,突变也是 true,那么应该返回 false

我的页面

  <div id="home">
    <div class="toggleTheme">
      <ToggleBtnTheme
        labelOn="Dark"
        labelOff="Light"
        v-model:value="isDark"
        @input="mode"
      />
    </div>
    <div class="title">
      <h1 :class="isDark ? 'dark' : 'light'">Lidian Manoha</h1>
    </div>
  </div>
</template>

<script>
import { mapMutations, mapGetters } from 'vuex';
import ToggleBtnTheme from '@/components/atoms/ToggleBtn/index';

export default {
  name: 'Home',
  components: {
    ToggleBtnTheme
  },

  methods: {
    ...mapMutations('themeDarkMode', ['toggleDarkMode']),
    mode() {
      this.toggleDarkMode();
    }
  },

  computed: {
    ...mapGetters('themeDarkMode', ['isDark'])
  },
  watch: {}
};
</script>

<style lang="scss" src="./style.scss" scoped></style>```

My Stores

    ```   return {
          darkMode: true,
          isDark: false
        };
      },
      getters: DarkModeGetters,
      mutations: DarkModeMutations,
      action: DarkModeAction
    };
    
    ```

My getters.js

    ```
    export default {
      isDark: state => state.isDark
    };
    ```

My mutations.js

    ```
    export default {
      toggleDarkMode: state => {
        state.isDark = !state.isDark;
        console.log('mutation', state.isDark);
        localStorage.setItem('DarkMode', JSON.stringify(state.isDark));
      }
    };```

And my ToggleBtn

    ```<template>
      <div id="toggleBtn">
        <div class="toggleBtnContainer">
          <label class="label" v-if="label">{{ label }}</label>
          <div class="containerToggle">
            <input
              v-bind="$attrs"
              :id="`toggle${uuid}`"
              :disabled="disabled"
              type="checkbox"
              :checked="value || checked"
              @change="$emit('update:value', $event.target.checked)"
            />
            <label
              :for="`toggle${uuid}`"
              v-html="value ? labelOn : labelOff"
              @click="$emit('click', $event)"
            ></label>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import { uuid } from 'vue-uuid';
    
    export default {
      name: 'toggleBtn',
      inheritAttrs: false,
      props: {
        value: { type: [Boolean, String, Number, Function], default: false },
        checked: { type: Boolean, default: false },
        labelOn: { type: String, default: 'off' },
        labelOff: { type: String, default: 'on' },
        label: { type: String, default: null },
        disabled: { type: Boolean, default: false }
      },
      data() {
        return {
          uuid: uuid.v4()
        };
      }
    };
    </script>
    
    <style lang="scss" src="./style.scss" scoped></style>```

【问题讨论】:

    标签: vue.js vuex


    【解决方案1】:

    那可能是因为你错过了一点。当您刷新页面时...即应用程序重新加载...如果您发现本地存储中有可用的数据('Darkmode'),那么您需要首先通过突变进行设置。通过这样做,当您刷新页面时会发生什么......如果darkmode已经设置为true,那么您的vuex state('isDark')也将设置为true。因此,当您单击它时,它将按预期切换。

    最好有两个突变以避免混淆

    My mutations.js
    
       
        export default {
          toggleDarkMode: state => {
            state.isDark = !state.isDark;
            console.log('mutation', state.isDark);
            localStorage.setItem('DarkMode', JSON.stringify(state.isDark));
          },
          initializeDarkMode: (state, payload) => {
            state.isDark = payload; // payload is actually the value that was stored in the local storage
          }
        };
    

    当应用加载时,只需调用第二个突变以使用本地存储值初始化状态。

      this.initializeDarkMode(DarkMode);  // DarkMode contains the value fetched from local storage
    

    下面我已经修改了调用第二个突变的代码

      <div id="home">
        <div class="toggleTheme">
          <ToggleBtnTheme
            labelOn="Dark"
            labelOff="Light"
            v-model:value="isDarkMode" // ****************Changes added ***************** 
            @input="mode"
          />
        </div>
        <div class="title">
          <h1 :class="isDark ? 'dark' : 'light'">Lidian Manoha</h1>
        </div>
      </div>
    </template>
    
    <script>
    import { mapMutations, mapGetters } from 'vuex';
    import ToggleBtnTheme from '@/components/atoms/ToggleBtn/index';
    
    export default {
      name: 'Home',
      components: {
        ToggleBtnTheme
      },
      data() {
        return {
         isDarkMode: this.isDark,
         },
       
      watch: {
         isDark(newVal) {
           this.isDarkMode = newVal;
         }
      },
    // ****************Changes added below ***************** 
      mounted() { 
       const isDark = localStorage.getItem('DarkMode');
       if(isDark && isDark === 'true') {
           this.initializeDarkMode(true); 
           this.isDarkMode = true;
        } else {
          this.initializeDarkMode(false);
          this.isDarkMode = false;
      }
      methods: {
        ...mapMutations('themeDarkMode', ['toggleDarkMode', 'initializeDarkMode']),
        mode() {
          this.toggleDarkMode();
        }
      },
    
      computed: {
        ...mapGetters('themeDarkMode', ['isDark'])
      },
      watch: {}
    };
    </script>
    
    <style lang="scss" src="./style.scss" scoped></style>
    

    【讨论】:

    • 另一方面非常感谢我不得不把 this.initializeDarkMode (DarkMode); // DarkMode 包含从本地存储中获取的值
    • 你是在问我是否需要包含第二个突变?
    • 我想知道我应该在哪里调用 this.initializeDarkMode (DarkMode);在我的代码中?对不起,我还是 vue 和 vuex 的初学者
    • 不要感到抱歉...检查我的更新答案
    • 谢谢,但他告诉我在 this.initializeDarkMode(DarkMode); 中没有定义 DarkMode;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 2021-09-14
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多