简体   繁体   中英

How can i change theme (dark / light ) in VueJS

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM