I am a beginner in Vite/Vue3 and currently I am facing a problem where I need the combined knowledge of the community.
I created a Vite/Vue3 application and installed 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
I then followed the instructions on the Tailwind homepage:
Add the paths of all template files in the tailwind.config.js file.
Import the newly created ./src/index.css file into the ./src/main.js file.
Create a ./src/index.css file and add the @tailwind directive Tailwind layer to each file.
Now I have a Vite/Vue3/TailwindCSS app running and want to add the ability to toggle dark mode.
Tailwind documentation says that archiving can be done by adding darkMode: 'class'
to tailwind.config.js
and then switching the class dark
to <html>
tag.
I accomplished this using the following code:
<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>
<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>
Yes, I know this is not Vue3 style code. And, yes, I know you can use element.classList.toggle()
instead of .remove()
and .add()
. But maybe other beginners like me will see this in the future and appreciate some simple code to start with. So please have mercy...
Now I finally have to ask the community a question:
I know that manipulating the DOM like this is not the Vue way of doing things. Of course, I want to achieve my goals in the right way. But what should I do?
Trust me, I searched on google for hours and didn't find a solution that works without installing this and this and this extra npm module.
But I wanted a minimalist approach. Depend on as little as possible so as not to overwhelm me and others who want to start learning.
With this as background - do you have a solution that would work for me and other newbies? :-)
The target element of your event is located outside your application. This means there is no way to interact with it other than querying it through the methods available in the DOM.
In other words, You did the right thing. If the element is inside your application, then you can just link the class to your attribute and let Vue handle the details of DOM manipulation:
but it is not the truth.
As a side note, it is very important that your toggle method does not depend on whether the
<body>
element has that class in order to decide if it should be applied/removed. You should persist the values saved in the application state, which should be your only source of truth.This is the Vue principle you don't want to break: let the data drive the DOM state, not the other way around.
The value can be obtained from the current state of
<body>
(when installed), but from that point on, changes to the application state will determine whether the class is present on the element.vue2 Example:
View 3 example:
Obviously, if you are using the state of
darkMode
in multiple components, you may want to keep the state ofdarkMode
somewhere outside ofdata
in storage, not locally (and provide it in your component viacompulated
).