是看了袁老师的视频后,自己做了一下练习。原视频地址:
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
// 主题
$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>
这样刷新的话也不会受到影响了