Reputation: 30054
I have a Vue application (a all-encompassing element with with several child components) to which I would like to add a night mode. I would like this night mode to be managed centrally, where the relevant styling would be applied to the elements which need to switch to night/day mode.
If I have an element (it is in the DOM as part of a component having been rendered, so not directly available to the parent component and therefore not bindable via v-bind
)
<div class="night-day">hello</div>
and two classes
.night {
background-color: black;
color: red
}
.day {
background-color: white;
color: black
}
is it possible to have night-day
pointing to either day
or night
(depending on some condition)?
Upvotes: 1
Views: 85
Reputation: 2854
you could use v-bind:class
(Class binding) from vue for this.
Like:
<div class="static" v-bind:class="{ night: isNight, day: !isNight }"></div>
Upvotes: 1
Reputation: 138696
You could use a class binding to bind a CSS class to a property, controlled by an event handler.
// MyComponent.vue
<template>
<div class="daynightdemo" :class="{ night: isNight }">
...
</div>
</template>
<script>
import { eventBus } from '@/eventBus'
export default {
data() {
return {
isNight: false
};
},
mounted() {
this.setNightDay = value => {
this.isNight = value === "night";
};
eventBus.$on("nightDay", this.setNightDay);
},
beforeDestroy() {
eventBus.$off("nightDay", this.setNightDay);
}
}
</script>
You mentioned the event bus being periodically called from setInterval
. In this example, the call would look like something like this:
// App.vue
export default {
mounted() {
let isNight = true;
setInterval(() => {
eventBus.$emit("nightDay", isNight ? "night" : "day");
isNight = !isNight;
}, LONG_INTERVAL);
}
};
Using Vuex, the boilerplate would be somewhat simplified, obviating the need for event-callback registration and unregistration:
// MyComponent.vue
<template>
<div class="daynightdemo" :class="{ night: $store.state.isNight }">
<h1>isNight: {{ $store.state.isNight }}</h1>
</div>
</template>
// App.vue
export default {
mounted() {
setInterval(() => {
this.$store.state.isNight = !this.$store.state.isNight;
}, 2000);
}
}
Upvotes: 1
Reputation: 274086
You can consider the use of CSS variables that you change within your JS code (setinterval). Basically you will have something like this:
<div class="night-day">hello</div>
.night-day {
background-color: var(--bc,black);
color: var(--c,red)
}
And within your JS you will have something like this:
var bc= ["black", "white"]
var c= ["red", "black"]
....
document.querySelector('.night-day').style.setProperty("--bc", bc[i]);
document.querySelector('.night-day').style.setProperty("--c", c[i]);
...
Where i
is an index that you can change based on your conditions:
Upvotes: 1
Reputation: 801
I think the best approach for solving the multiple themes problem would be to have a theme class modifier on the body
tag and in your CSS, modify your subelements accordingly. Here's an example to clarify things up.
<body class="dark-theme">
<div class="container">
Content...
</div>
</body>
.container {
background-color: white;
color: black
}
.dark-theme .container {
background-color: black;
color: red
}
Toggling .dark-theme
on the body
, in this case, would switch between the default theme and the dark theme.
Upvotes: 1