Vue + Tailwind 2.0: Vuex, localStorage 및 사용자의 기본 설정을 사용하는 다크 모드

TailwindCSS 2.0 아프다. 기본 다크 모드, 수많은 색상, 수많은 기타 똥. 우연히 Tailwind 2.0이 출시되었을 때 최근에 개발한 차 의존성을 문서화하기 위한 새로운Gridsome 프로젝트를 시작하게 되었고, 앞으로 다가올 어두운 시대를 표현하기 위해 몇 가지 테마 토글을 추가하고 싶었습니다.

내가 원하는 조건부 테마는 약간 복잡합니다.
  • 처음 방문자에게 OS/브라우저 선호 테마가 표시되어야 함
  • 세션 내내 사용자의 테마 선택을 존중해야 함
  • 사용자가 선택한 테마를 로컬 저장소에 저장해야 돌아올 때 UI와 씨름할 필요가 없습니다
  • .

    Tailwind에는 테마 선택을 수동 모드로 전환하는 옵션이 있지만 운전 스틱에 대한 문서의 예는 모호하고 의도적으로 구체적이지 않습니다. CTRL+C CTRL+V는 여기에서 우리에게 큰 도움이 되지 않으므로 VS Code에서 우리는 스스로 합니다.

    VuexlocalStorage을 사용하여 고유한 상태 저장 다크 모드 솔루션을 구현해 보겠습니다.

    깊은 상태



    Vuex를 기존 Gridsome 프로젝트에 45분 동안 추가하려고 노력한 후 공식 Gridsome 문서가 나를 다시 console.error 총살대에 데려가기로 결정한 후, 결국 저는 Vuex의 자랑스러운 아버지가 되는 지점에 도달했습니다. 가게:

    import Vue from 'vue'
    import Vuex from 'vuex'
    import theme from './modules/theme'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
        state: {},
        mutations: {},
        actions: {},
        modules: {
            theme
        },
    })
    


    이제 해당 theme.js 모듈 내에서 우리의 로직 대부분을 프런트엔드에서 멀리 두는 몇 가지 간단한 트릭을 수행할 수 있습니다. 상태 및 돌연변이부터 시작하겠습니다.

    export default {
        state: {
            theme: {}
        },
        mutations: {
            SET_THEME(state, theme) {
                state.theme = theme;
                localStorage.theme = theme;
            }
        },
    ...
    


    변이를 놀라울 정도로 단순하게 유지하여 변이의 유일한 책임이 테마의 상태를 업데이트하는 것입니다. 이를 localStorage에 저장하면 기본적으로 쿠키처럼 페이지를 닫았다가 나중에 다시 방문한 후 사용자가 가장 최근에 선택한 테마를 검색할 수 있습니다.

    이제 처음 사용자가 사이트를 방문했을 때 어떤 일이 발생하는지 생각해 보십시오. 그들이 OS나 브라우저에서 밝거나 어두운 테마를 선택했을 가능성이 있으며, 우리는 이를 존중할 수 있고 존중해야 합니다. 아직 테마 상태를 초기화하지 않았습니다. 이것이 우리의 첫 번째 조치가 될 것입니다.

    ...
     actions: {
            initTheme({ commit }) {
    
                const cachedTheme = localStorage.theme ? localStorage.theme : false;
                //  `true` if the user has set theme to `dark` on browser/OS
                const userPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    
                if (cachedTheme)
                    commit('SET_THEME', cachedTheme)
                else if (userPrefersDark)
                    commit('SET_THEME', 'dark')
                else
                    commit('SET_THEME', 'light')
    
            },
    ...
    


    이 작업은 사용자가 이전에 사이트를 방문한 적이 있는지 확인합니다.
  • 그렇다면 캐시된 테마 기본 설정을 사용합니다.
  • 새로운 사람인 경우 시스템이 어두운 모드로 설정되어 있는지 확인합니다. 그렇다면 스토어 및 캐시를 다크 모드로 전환합니다.
  • 그렇지 않으면 기본적으로 밝은 모드로 설정합니다.

  • 진입 지점에 관계없이 모든 사람이 적중할 앱의 편재하는 루트에서 이 작업을 발송할 수 있습니다.

    // for me this is `layouts/Default.vue`, but for you it may be `App.vue` or something else
    export default {
      beforeMount() {
        this.$store.dispatch("initTheme");
      },
    ...
    


    이제 테마를 전환하려면 스위치가 필요합니다.

    구성 요소를 만들기 전에 논리를 추가하기 위해 theme.js로 돌아가 보겠습니다.

    ...
    // This simply flips whatever was most recently committed to storage.
        toggleTheme({ commit }) {
    
                switch (localStorage.theme) {
                    case 'light':
                        commit('SET_THEME', 'dark')
                        break;
    
                    default:
                        commit('SET_THEME', 'light')
                        break;
                }
            }
        },
        getters: {
            getTheme: (state) => {
                return state.theme;
            }
        },
    }
    


    Tailwind 2.0의 다크 클래스



    여기에서 일부 속성을 추가하여 다크 모드에서 조건부로 렌더링할 수 있습니다. 그런 다음 Tailwind의dark css 클래스를 앱의 루트 노드에 추가 및 제거하는 함수를 실행하여 테마 선택의 변경 사항에 반응하는 감시자를 설정합니다.

    <template>
      <main
        class="min-h-screen 
               bg-green-50 text-gray-700 
               dark:bg-gray-900 dark:text-purple-50">
        <ThemeToggler/>
        <slot />
      </main>
    </template>
    
    <script>
    import { mapGetters } from "vuex";
    import ThemeToggler from "../components/ThemeToggler.vue";
    
    export default {
      components: {
        ThemeToggler,
      },
      beforeMount() {
        this.$store.dispatch("initTheme");
      },
      computed: {
        ...mapGetters({ theme: "getTheme" }),
      },
      watch: {
        theme(newTheme, oldTheme) {
          newTheme === "light"
            ? document.querySelector("html").classList.remove("dark")
            : document.querySelector("html").classList.add("dark");
        },
      },
    };
    </script>
    


    그리고 마지막 부분은 믿을 수 없을 정도로 실망스러운 토글러입니다.

    <template>
        <button 
         @click="toggleTheme"
         class="dark:text-red-400 text-cyan-200">
          Theme Toggle
        </button>
    </template>
    
    <script>
    export default {
      methods: {
        toggleTheme() {
          this.$store.dispatch("toggleTheme");
        },
      },
    };
    </script>
    


    창작의 자유



    야생을 얻을 수 있고 일부 SVG로 텍스트를 교체하고 상태 간 변환을 위해 wazoo 외부에 전환을 추가할 수 있기 때문에 이것은 아름답습니다. Vue의 내장 전환 요소나 Tailwind의 전환 클래스 또는 둘 다를 사용할 수 있습니다!

    질문, 제안 또는 보다 우아한 솔루션이 있는 경우 아래에 게시하십시오! 루트 요소에서 dark 클래스를 바닐라 처리하는 대신 Vue의 조건부 클래스를 사용하는 것과 같이 더 우아할 수 있는 몇 가지 영역을 발견했습니다.

    좋은 웹페이지 즐겨찾기