I have a problem in VueJS. I coding a website and i want to add a sun icon. I want to change theme when click icon. You knows; if theme is dark do light and the exact opposite. I think emit() is not work. But I am not sure. This is codes:
Navbar.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
defineEmits(['toggle'])
</script>
<template>
<div>
<nav class="navbar navbar-expand-lg" id="navbar">
<div class="container-fluid">
<a href="/" class="navbar-brand">
<span>osman<span>beyhan</span></span>
</a>
<div class="iconsTwo">
<i class="bi bi-sun-fill d-block d-lg-none" id="icon" @click="this.$emit('toggle')"></i>
<i class="bi bi-list navbar-toggler" data-bs-toggle="offcanvas" href="#offcanvasMenu" aria-controls="offcanvasMenu"></i>
</div>
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasMenu" aria-labelledby="offcanvasMenuLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasMenuLabel">
<a href="/">
<span>osman<span>beyhan</span></span>
</a>
</h5>
<i class="bi bi-x-lg btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></i>
</div>
<div class="offcanvas-body">
<ul class="navbar-nav">
<li class="nav-item">
<a class="" href="/about">About Me</a>
</li>
<li class="nav-item">
<a class="" href="/projects">Projects</a>
</li>
<li class="nav-item">
<a class="" href="/contact">Contact</a>
</li>
</ul>
<hr id="line">
<ul class="nav-item d-flex d-md-flex" id="icons">
<li>
<a class="" target="_blank" href="https://www.instagram.com/osmn_byhn/?hl=tr">
<i class="fa-brands fa-instagram"></i>
</a>
</li>
<li>
<a class="" target="_blank" href="https://github.com/osmn-byhn">
<i class="fa-brands fa-github"></i>
</a>
</li>
<li>
<a class="" target="_blank" href=" https://wa.me/905350217844">
<i class="fa-brands fa-whatsapp"></i>
</a>
</li>
<li>
<a class="" target="_blank" href="https://www.linkedin.com/in/osman-beyhan-12304b23a/">
<i class="fa-brands fa-linkedin"></i>
</a>
</li>
<br>
<li id="ayrac" class="d-none d-lg-block"> | </li>
<li>
<i class="bi bi-sun-fill d-none d-lg-block mysun" id="icon"></i>
</li>
</ul>
</div>
</div>
</div>
</nav>
</div>
</template>
<style lang="scss" scoped>
@import '/public/Navbar.scss';
@import '/public/Theme.scss';
</style>
App.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
import Navbar from './components/Navbar.vue'
import { ref } from 'vue'
var mode = ref('dark')
function toggle() {
if (mode === "dark") {
mode = "light"
console.log(mode)
} else {
mode = "dark"
console.log(mode)
}
}
</script>
<template>
<div class="app" :class="mode">
<Navbar :mode="mode" @toggle="toggle" />
<RouterView />
</div>
</template>
<style scoped lang="scss">
@import '../public/App.scss';
@import '../public/Theme.scss';
</style>
When i click sun icon; function is works but theme don't change: enter image description here
Please help me
In the script setup
syntax, you shouldn't use $this
when emitting something, instead you should handle it like this:
<script setup>
// more logic ...
const emit = defineEmits(["toggle"]);
</script>
<template>
<div>
<button @click="emit('toggle', someData)">toggle theme</button>
</div>
</template>
Then in the parent component:
<script setup>
const handleData = (param) => {
console.log("data passed was ", param);
}
</script>
<template>
<MyComponent @toggle="handleData()">
...
</MyComponent>
</template>
But also, you could just add the dark
class to the body, and while it's outside the vue app
instance, you could just handle the logic directly in the Navbar
component and adding the class in vanilla javascript:
<!-- Navbar component, without emit -->
<script setup>
const toggle = () => {
if(document.body.classList.contains("dark")){
document.body.classList.remove("dark");
}else{
document.body.classList.add("dark");
}
}
</script>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.