美文网首页vue
vue3 实现主题切换

vue3 实现主题切换

作者: 暴躁程序员 | 来源:发表于2024-09-05 14:54 被阅读0次

    一、方式一:自定义主题(常规版)

    1. 在 src/assets/theme.scss 中定义不同主题变量
    html[data-theme='default'] {
      --color-page-bg: #fff;
      --color-page-fs: #000;
      --size-page-fs: 20px;
    }
    
    html[data-theme='dark'] {
      --color-page-bg: #000;
      --color-page-fs: #fff;
      --size-page-fs: 20px;
    }
    
    html[data-theme='red'] {
      --color-page-bg: red;
      --color-page-fs: #fff;
      --size-page-fs: 20px;
    }
    
    1. 在入口 main.js 中注册
    import '@/assets/theme.scss'
    
    1. 在 index.html 中,定义 data-theme 属性和默认主题值 default
    <!doctype html>
    <html lang="en" data-theme="default">
      <head>
        <meta charset="UTF-8" />
        <link rel="icon" href="/favicon.ico" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Vite App</title>
      </head>
    
      <body>
        <div id="app"></div>
        <script type="module" src="/src/main.js"></script>
      </body>
    </html>
    
    1. 在 src/App.vue 中,初始化主题
    <script setup>
    import { RouterView } from 'vue-router'
    import { ref } from 'vue'
    // 初始化主题
    if (localStorage.getItem('current-theme')) {
      const currentTheme = ref(localStorage.getItem('current-theme'))
      document.documentElement.setAttribute('data-theme', currentTheme.value)
    }
    </script>
    
    <template>
      <RouterView />
    </template>
    
    1. 在 src/views/HomeView.vue 中,实现切换主题
    <script setup>
    // 切换主题
    const fnToggle = (theme) => {
      localStorage.setItem('current-theme', theme)
      document.documentElement.setAttribute('data-theme', theme)
    }
    
    const themeOptions = [
      {
        label: '默认主题',
        value: 'default'
      },
      {
        label: '暗黑主题',
        value: 'dark'
      },
      {
        label: '红色主题',
        value: 'red'
      }
    ]
    </script>
    
    <template>
      <div class="wrapper">
        <h1>vue 主题切换</h1>
        <div>hello world</div>
        <button v-for="item in themeOptions" :key="item.label" @click="fnToggle(item.value)">
          {{ item.label }}
        </button>
      </div>
    </template>
    <style>
    .wrapper {
      height: 100vh;
      width: 100vw;
      overflow-y: auto;
      box-sizing: border-box;
      background: var(--color-page-bg);
      color: var(--color-page-fs);
      font-size: var(--size-page-fs);
    }
    </style>
    

    二、方式二:通过 style.filter 属性实现主题切换

    1. 在 src/App.vue 中实现
    <script setup>
    import { ref } from 'vue'
    
    // 1、初始化模式、主题
    const colorAreaValue = ref(Number(localStorage.getItem('style-filter-color')) || 0)
    const isDark = localStorage.getItem('style-filter-dark') === 'true' ? true : false
    const darkValue = ref(isDark || false)
    if (!darkValue.value) {
      document.documentElement.style.filter = `hue-rotate(${colorAreaValue.value}deg)`
    } else {
      document.documentElement.style.filter = `invert(${darkValue.value ? '85' : '0'}%)`
    }
    // 2、切换主题
    const changeTheme = (v) => {
      document.documentElement.style.filter = `hue-rotate(${v}deg)`
      localStorage.setItem('style-filter-color', v)
      localStorage.setItem('style-filter-dark', false)
      darkValue.value = false // 主题变更要切换到普通模式
    }
    // 3、切换模式
    const changeMode = (v) => {
      document.documentElement.style.filter = `invert(${v ? '85' : '0'}%)`
      localStorage.setItem('style-filter-dark', v)
      if (!v) {
        document.documentElement.style.filter = `hue-rotate(${colorAreaValue.value}deg)` // 切换到普通模式、主题要生效
      }
    }
    // 置灰模式
    const changeGrayMode = () => {
      document.documentElement.style.filter = `grayscale(100%)`
    }
    </script>
    <template>
      <div class="slider-demo-block">
        <div style="width: 40px">主题</div>
        <el-slider v-model="colorAreaValue" @input="changeTheme" show-input :max="360" />
      </div>
      <div class="slider-demo-block">
        <div style="width: 40px">模式</div>
        <el-switch
          v-model="darkValue"
          @change="changeMode"
          class="ml-2"
          inline-prompt
          style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
          active-text="普通模式"
          inactive-text="暗黑模式"
        />
      </div>
      <div style="margin: 20px 0">
        <el-button type="primary" @click="changeGrayMode">置灰模式</el-button>
      </div>
      <div class="mb-4">
        <el-button>Default</el-button>
        <el-button type="primary">Primary</el-button>
        <el-button type="success">Success</el-button>
        <el-button type="info">Info</el-button>
        <el-button type="warning">Warning</el-button>
        <el-button type="danger">Danger</el-button>
      </div>
    </template>
    
    <style lang="scss">
    body {
      background: #f9f9f9;
    }
    .slider-demo-block {
      max-width: 600px;
      display: flex;
      align-items: center;
    }
    .slider-demo-block .el-slider {
      margin-top: 0;
      margin-left: 12px;
    }
    </style>
    
    1. 由于此方式是借助 css 的 filter 过滤属性实现的主题、模式切换,因此:
    1. 此方式不需要定义主题文件
    2. 此方式是通过 document.documentElement.style.filter 将过滤属性作用于全局
    3. 此方式无法操作局部颜色
    

    相关文章

      网友评论

        本文标题:vue3 实现主题切换

        本文链接:https://www.haomeiwen.com/subject/fvzrljtx.html