是看了袁老师的视频后,自己做了一下练习。原视频地址:
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";'
- }
- }
- }
- })
然后就可以进行测试了
- <div class="test">
- 123
- div>
-
- <el-switch v-model="flag" @change="change">el-switch>
-
- <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自定义属性,值就是我们存本地的值
-
- <template>
- <RouterView />
- template>
-
- <style lang="scss">
- * {
- padding: 0;
- margin: 0;
- box-sizing: border-box;
- }
-
- html,body,#app {
- width: 100%;
- height: 100%;
- }
- style>
这样刷新的话也不会受到影响了