HowTo : Basculer en mode sombre avec TailwindCSS + Vue3 + Vite

Je suis un débutant concernant Vite/Vue3 et actuellement je suis confronté à un problème où j'ai besoin des connaissances combinées de la communauté.

J'ai créé une application Vite/Vue3 et y ai installé TailwindCSS :

npm create vite@latest my-vite-vue-app -- --template vue
cd my-vite-vue-app
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Ensuite, j'ai suivi les instructions sur la page d'accueil de Tailwind :

Ajoutez les chemins d'accès à tous vos fichiers de modèle dans votre fichier tailwind.config.js.
Importez le fichier./src/index.css nouvellement créé dans votre fichier./src/main.js. Créez un fichier./src/index.css et ajoutez les directives @tailwind pour chacune des couches de Tailwind.

Maintenant, j'ai une application Vite/Vue3/TailwindCSS fonctionnelle et je souhaite ajouter la fonctionnalité permettant de basculer en mode sombre.

La documentation Tailwind indique que cela peut être archivé en ajoutant puis darkMode: 'class'en basculant la classe pour la balise.tailwind.config.jsdark<html>

J'ai fait ce travail en utilisant ce code:

  • Dans index.html

  • <html lang="en" id="html-root">
    (...)
    <body class="antialiased text-slate-500 dark:text-slate-400 bg-white dark:bg-slate-900">
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
    </body>
    </html>

  • À propos de.vue

  • <template>
    <div>
    <h1>This is an about page</h1>
    <button @click="toggleDarkMode">Toggle</botton>
    </div>
    </template>
    <script>
    export default {
    methods: {
    toggleDarkMode() {
    const element = document.getElementById('html-root')
    if (element.classList.contains('dark')) {
    element.classList.remove('dark')
    } else {
    element.classList.add('dark')
    }
    },
    },
    };
    </script>

    Oui, je sais que ce n'est pas du code de style Vue3. Et, oui, je sais qu'on pourrait faire à la element.classList.toggle()place de .remove()et .add(). Mais peut-être que d'autres débutants comme moi se pencheront sur cela à l'avenir et seront reconnaissants pour un code peu sophistiqué pour commencer. Alors s'il te plait aie pitié...

    J'en viens enfin à la question que je veux poser à la communauté:

    Je sais que manipuler le DOM comme ça n'est pas la façon de faire de Vue. Et, bien sûr, je veux archiver mon objectif de la bonne manière. Mais comment puis-je faire cela?

    Croyez-moi, j'ai cherché sur Google pendant quelques heures, mais je n'ai pas trouvé de solution qui fonctionne sans installer ceci et ceci et ce module npm supplémentaire.

    Mais je veux avoir une approche minimaliste. Aussi peu de dépendances que possible afin de ne pas me submerger, moi et les autres qui veulent commencer à apprendre.

    Ayant cela comme arrière-plan - les gars et les filles avez-vous une solution pour moi et les autres débutants ?:-)


    Solution du problème

    L'élément cible de votre événement est en dehors de votre application. Cela signifie qu'il n'y a pas d'autre moyen d'interagir avec lui qu'en l'interrogeant via les méthodes disponibles du DOM.

    En d'autres termes, vous le faites correctement. Si l'élément se trouvait dans l'application, vous lieriez simplement la classe à votre propriété et laisseriez Vue gérer les spécificités de la manipulation du DOM :

    :class="{ dark: darkMode }"

    Mais ce n'est pas.

    En remarque, il est vraiment important que votre méthode toggle ne dépende pas du fait que l' <body>élément ait ou non la classe, afin de décider s'il doit être appliqué/supprimé. Vous devez conserver la valeur enregistrée dans l'état de votre application et cela doit être votre seule source de vérité.
    C'est le principe de Vue que vous ne voulez pas casser : laissez les données piloter l'état du DOM, et non l'inverse.

    Vous pouvez obtenir la valeur (au montage) à partir de l'état actuel de <body>, mais à partir de ce moment, les modifications apportées à l'état de votre application détermineront si la classe est présente ou non sur l'élément.

    exemple vue2 :


    Vue.config.devtools = false;
    Vue.config.productionTip = false;
    new Vue({
    el: '#app',
    data: () => ({
    darkMode: document.body.classList.contains('dark')
    }),
    methods: {
    applyDarkMode() {
    document.body.classList[
    this.darkMode? 'add': 'remove'
    ]('dark')
    }
    },
    watch: {
    darkMode: 'applyDarkMode'
    }
    })

    body.dark {
    background-color: #191919;
    color: white;
    }

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
    <div id="app">
    <label>
    <input type="checkbox" v-model="darkMode">
    dark mode
    </label>
    </div>

    Commentaires

    Posts les plus consultés de ce blog

    Erreur Symfony : "Une exception a été levée lors du rendu d'un modèle"

    Détecter les appuis sur les touches fléchées en JavaScript

    Une chaîne vide donne "Des erreurs ont été détectées dans les arguments de la ligne de commande, veuillez vous assurer que tous les arguments sont correctement définis"