结合scss实现黑白主题切换

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

b站地址https://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

css 复制代码
// 主题
$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,重新启动一下

javascript 复制代码
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";'
      }
    }
  }
})

然后就可以进行测试了

javascript 复制代码
<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自定义属性,值就是我们存本地的值

javascript 复制代码
<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>

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

相关推荐
undefined&&懒洋洋6 分钟前
Web和UE5像素流送、通信教程
前端·ue5
大前端爱好者2 小时前
React 19 新特性详解
前端
随云6322 小时前
WebGL编程指南之着色器语言GLSL ES(入门GLSL ES这篇就够了)
前端·webgl
随云6322 小时前
WebGL编程指南之进入三维世界
前端·webgl
寻找09之夏3 小时前
【Vue3实战】:用导航守卫拦截未保存的编辑,提升用户体验
前端·vue.js
非著名架构师3 小时前
js混淆的方式方法
开发语言·javascript·ecmascript
多多米10054 小时前
初学Vue(2)
前端·javascript·vue.js
敏编程4 小时前
网页前端开发之Javascript入门篇(5/9):函数
开发语言·javascript
柏箱4 小时前
PHP基本语法总结
开发语言·前端·html·php
新缸中之脑4 小时前
Llama 3.2 安卓手机安装教程
前端·人工智能·算法