结合scss实现黑白主题切换

是看了袁老师的视频后,自己做了一下练习。原视频地址:

b站地址icon-default.png?t=N7T8https://www.bilibili.com/video/BV15z4y1N7jB/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=c6cf63302f28d94ebc02cbedcecc57ea首先创建一个全局的scss文件。我这里放在了assets文件夹中,创建了一个theme的文件夹,里面放置了一个theme.scss

// 主题
$themes: (
    // 白亮
    light: (
        background: #fff,
        color: #000,
        textColor: #000
    ),
    // 暗黑
    dark: (
        background: #121212,
        color: #fff,
        textColor: #fff
    )
);

// 当前主题
$curTheme: light;

// 混合
// @mixin useTheme() {
//     html[data-theme='light'] & {
//         background-color: #fff;
//         color: #000;
//     }
//     html[data-theme='dark'] & {
//         background-color: #121212;
//         color: #fff;
//     }
// }

// 混合优化(遍历上面的主题)
@mixin useTheme() {
    @each $key, $value in $themes {
        $curTheme: $key !global; // 当前的主题
        html[data-theme = #{$key}] & { // & 表示传入什么选择器就是什么选择器
            @content; // 类似于插槽,样式可以进行传入
        }
    }
}

// 生成对应主题的变量
@function getVar($key) {
    $themeMap: map-get($themes, $curTheme);
    @return map-get($themeMap, $key);
}

然后通过vite进行这个scss文件的全局配置,这样就不用多次引入了。修改vite.config.ts文件。修改之后记得重新npm run dev,重新启动一下

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  // 上面的是默认的
  css: { // 引入全局的scss文件
    // css预处理器
    preprocessorOptions: {
      scss: {
        // 引入 theme.scss 这样就可以在全局中使用 theme.scss中预定义的变量和方法了
        // 给导入的路径最后加上 ; 
        additionalData: '@import "./src/assets/theme/theme.scss";'
      }
    }
  }
})

然后就可以进行测试了

<template>
  <div class="test">
    123
  </div>

  <el-switch v-model="flag" @change="change"></el-switch>
</template>

<script setup lang="ts">
import { ref } from 'vue'

// 这里从本地取是为了保持刷新以后也能一致
const flag = ref(localStorage.getItem('theme') === 'dark' ? true : false)

const change = (flag: boolean) => {
  localStorage.setItem('theme', flag ? 'dark' : 'light') // 存本地,刷新的时候会用
  // 控制html标签,给自定义属性data-theme添加对应的值,这样对应的样式就会生效
  document.querySelector('html')?.setAttribute('data-theme', flag ? 'dark' : 'light')
}
</script>

<style lang="scss">
// 由于vite已经配置过了,所以不需要引入了。如果引入失败,那就老老实实在使用的文件中都引入
// @import '../assets/theme/theme.scss'; 

// 使用测试
.test {
  // 共有样式部分
  width: 100px;
  height: 100px;

  // 黑白主题特有部分样式
  @include useTheme() {
    background-color: getVar('background');
    color: getVar('color');
  }
}
</style>

白亮的

暗黑的

但是会有一个问题,就是刷新的时候,发现html标签的data-theme自定义属性丢失了。所以就需要在App.vue文件中,重新再给html标签设置一下data-theme自定义属性,值就是我们存本地的值

<script setup lang="ts">
import { RouterView } from 'vue-router'

// 添加主题,每次刷新的时候还是原先选择的主题
let theme = localStorage.getItem('theme') || 'light'
document.documentElement.setAttribute('data-theme', theme)
</script>

<template>
  <RouterView />
</template>

<style lang="scss">
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,body,#app {
  width: 100%;
  height: 100%;
}
</style>

这样刷新的话也不会受到影响了

猜你喜欢

转载自blog.csdn.net/qq_52845451/article/details/134440561
今日推荐