vue实现多窗口主题样式切换以及跟随系统切换

vue实现多窗口主题样式切换以及跟随系统切换

自我记录

一.知识点链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/@media/prefers-color-scheme
一.知识点链接:https://www.runoob.com/jsref/met-win-matchmedia.html
二.监听 storage 变动 (跨页签通信)
三.watchEffect 侦听器

一.js+css 去匹配系统主题颜色

// 使用matchMedia API 去匹配css的媒体查询的 系统的主题是否为案(dark)颜色 (也可以去匹配屏幕的宽度高度等)
const match = matchMedia('(prefers-color-scheme:dark)')
console.log(match,'match');

在这里插入图片描述

二. 跨标签通信

window.addEventListener('storage', (event) => {
      console.log(event.newValue)
    })

A页面存储发生变化时B页面可以监听到
在这里插入图片描述

三.监听本地存储的变化并赋值

watchEffect(() => {
 localStorage.setItem(LOCAL_KEY, theme.value)
 document.documentElement.className = theme.value
})

四.全部代码

<template>
  <a-layout-header class="head-box" :style="{ position: 'fixed', zIndex: 1, width: '100%' }">
    <a-row :gutter="{ xs: 24, sm: 24, md: 24, lg: 24 }">
      <a-col :xs="7" :sm="7" :md="7" :lg="7">奔跑的代码!</a-col>
      <a-col :xs="6" :sm="6" :md="6" :lg="6">奔跑的代码!</a-col>
      <a-col :xs="6" :sm="6" :md="6" :lg="6">奔跑的代码!</a-col>
      <a-col :xs="5" :sm="5" :md="5" :lg="5">
        <!-- 开关切换主题 -->
        <a-switch v-model:checked="checked" checked-children="经典" un-checked-children="深夜" @change="onChange" />
      </a-col>
    </a-row>
  </a-layout-header>
</template>
<script setup>
import { ref, watchEffect } from 'vue'

const checked = ref(false)
// 切换主题样式
// 'light' | 'dark'
const LOCAL_KEY = '__theme__'
const theme = ref(localStorage.getItem(LOCAL_KEY) || 'light')
// 使用matchMedia API 去匹配css的媒体查询的 系统的主题是否为案(dark)颜色 (也可以去匹配屏幕的宽度高度等)
const match = matchMedia('(prefers-color-scheme:dark)')
console.log(match,'match');
// 跟随系统
const followOs = () => {
  // 如果当前系统时暗色 
  if (match.matches) {
  	// 本地存储重新赋值
    localStorage.setItem(LOCAL_KEY, 'dark')
    // html 的class 重新赋值
    document.documentElement.className = 'dark'
    // 优化了 页面滑块按钮的赋值
    checked.value = true
  } else {
    localStorage.setItem(LOCAL_KEY, 'light')
    document.documentElement.className = 'light'
    checked.value = false
  }
}
// matchMedia 的API 当 matchMedia('(prefers-color-scheme:dark)') 查询结果有变化时
// 监听主题的变化 
match.addEventListener('change', followOs)

watchEffect(() => {
  // 仅需要多个标签页联动 用这俩  
  // localStorage.setItem(LOCAL_KEY, theme.value)
  // document.documentElement.className = theme.value
  // 使用跟随系统功能 用这个函数
  followOs()
})
// 这个是antd滑块的事件 
const onChange = (value) => {
  const temp = value ? 'dark' : 'light'
  if (value) {
    theme.value = temp
    localStorage.setItem(LOCAL_KEY, temp)
    document.documentElement.className = temp
  } else {
    theme.value = temp
    localStorage.setItem(LOCAL_KEY, temp)
    document.documentElement.className = temp
  }


};
// 监听本地存储的变化 为了实现多个标签页联动
addEventListener('storage', event => {
  console.log(event, 'ev');
  document.documentElement.className = event.newValue
  checked.value = event.newValue === 'light' ? false : true
})

</script>
<style lang="less" scoped>
.head-box {
  width: 100%;
  height: 64px;
  background: @bgc-head-color;
  padding: 0 20px;
}
</style>

element Plus主题切换

最终展示效果

实现功能所用的代码API都在上面 大家也可以根据自己的喜好实现 想要的功能
起初只实现了一个主题切换功能 昨天有个朋友突然跟我说她的神仙产品经理要一个跟element Plus一样的多个标签页联动主题切换功能
接下来就有了上面的代码 如果帮到你了 请点赞收藏多多支持!

下面是我记录一下 简单配置vite+vue3+antd的主题切换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
vite.config.js

import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue' //是vite 对vue 对支持插件
import Components from 'unplugin-vue-components/vite'
import path from 'path'
import themePreprocessorPlugin from "@zougt/vite-plugin-theme-preprocessor";
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'

// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
    return {
        plugins: [
            vue(),
            VueSetupExtend(),
            Components({
                resolvers: [
                    AntDesignVueResolver({
                        importStyle: 'less', // 一定要开启这个配置项
                    }),
                ],
            }),
            themePreprocessorPlugin({
                less: {
                    // 各个主题文件的位置
                    multipleScopeVars: [
                        {
                            scopeName: "light",
                            path: path.resolve("src/assets/style/light.less"),
                        },
                        {
                            scopeName: "dark",
                            path: path.resolve("src/assets/style/dark.less"),
                        },
                    ],
                },
            }),
        ],
        base: "./",//公共基础路径 打包路径
        resolve: {
            alias: {
                '@': path.resolve(__dirname, './src')//别名设置
            },
            extensions: ['.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
        },
        server: {
            // host: 'localhost',
            port: 8081,//启动端口
            // https: true, // 开启https
            open: true, // 自动开启窗口
            proxy: { // 代理配置
                '/api': {
                    target: 'xxx',//后端服务地址
                    changeOrigin: true,
                    rewrite: (path) => path.replace(/^\/api/, '') // 重写路径
                }
            },
        },
        css: {
            preprocessorOptions: {
                less: {
                    // modifyVars:
                    //     {
                    //         'primary-color': '#1DA57A',
                    //         'link-color': '#1DA57A',
                    //         'border-radius-base': '2px',
                    // },
                    additionalData: `@import './src/assets/style/index.less';`,
                    javascriptEnabled: true,
                },
                stylus: {
                    /*vite  根据官档  @import 引入stylus不生效 需要通过绝对路径导入 */
                    // imports: [path.resolve(__dirname, 'src/stylus/...styl')]  //配置全局变量
                }
            },
        },
    }
})

总结不易,希望对各位有所帮助.希望可以共同学习与进步.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue实现一套切换系统主题的代码,可以按照以下步骤: 1. 定义主题样式表的类名 在实现主题切换时,通常需要用到多个不同的样式表。为了方便统一管理这些样式表,需要为每一个样式表定义一个唯一的类名。可以通过定义一些全局变量或者配置文件来存储这些类名,例如: ```javascript // 全局变量 const themeClasses = { 'dark': 'theme-dark', 'light': 'theme-light' } // 配置文件 export const themeClasses = { 'dark': 'theme-dark', 'light': 'theme-light' } ``` 2. 定义全局样式表 在Vue的全局样式表(通常为`App.vue`组件中的`<style>`标签)中,可以使用变量的方式定义系统主题样式。例如: ```css /* 定义变量 */ :root { --primary-color: #428bca; --secondary-color: #5cb85c; } /* 定义主题样式 */ .theme-dark { --primary-color: #555555; --secondary-color: #CCCCCC; } .theme-light { --primary-color: #EEEEEE; --secondary-color: #00aacc; } /* 使用变量 */ .button { color: var(--primary-color); background-color: var(--secondary-color); } ``` 3. 切换主题实现主题切换时,通常需要监听一个切换按钮的点击事件,并在事件回调函数中修改全局样式表中的`<style>`标签。可以使用`document.documentElement`来获取`<style>`标签,并在其`innerHTML`属性中修改主题样式。例如: ```javascript // 切换按钮的点击事件 toggleTheme() { // 判断当前主题,并计算下一个主题 const currentTheme = this.theme; const nextTheme = currentTheme === 'dark' ? 'light' : 'dark'; // 获取全局样式表并修改样式 const style = document.documentElement.querySelector('style'); style.innerHTML = style.innerHTML.replace(currentTheme, nextTheme); // 更新当前主题 this.theme = nextTheme; } ``` 通过以上步骤,便可以实现一套简单的主题切换系统。需要注意的是,如果主题样式较多或者样式表较大时,切换主题可能会造成性能问题。可以考虑使用CSS变量或者动态生成样式表来提高性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值