Vue UI框架的主题切换功能实现

目录
  • AntD 的方式
    • 1. 创建黑暗主题文件
    • 2. 创建切换主题的函数
    • 3. 切换主题
  • Quasar 的方式
  • ElementUI 的方式
  • NaiveUI 的方式

在如今,很多网页已经可以手动切换明亮模式和黑暗模式,网页的主题切换已经成为了一个常用的需求,因此,本文将从常见框架的处理方式总结一些相关的操作,并探究其本质。

AntD 的方式

AntD 的 config-provider 似乎不能直接修改主题,目前网络上的教程有两类,一类是通过 less 的修改变量修改来完成,另一类是操作 DOM 改变对文件的引用,由于 ant-design-vue 已经提供了黑暗主题,而且直接修改 less 文件的变量涉及到了太多变量,不太方便,因此参考了这篇文章vue3点击出现弹窗后背景变暗且不可操作的实现代码,使用动态添加 CSS 引用 DOM 的方式实现黑暗主题的切换,原理是添加一个 DOM,引用我们自定义的 CSS 样式,后面的引用会覆盖前面的引用,在切换到亮色主题时把这个 DOM 删除。

1. 创建黑暗主题文件

在目录下的适当位置创建一个黑暗主题的文件,后面要引用这个文件,这里直接把官方黑暗主题复制过来就可以了,它的位置在 node_modules\ant-design-vue\dist\antd.dark.min.css,假设我们把它复制到了 public/styles/dark.css 中。

2. 创建切换主题的函数

有了主题文件,我们就可以创建切换主题的函数了,在目录中的合适位置创建一个 js 文件,例如 src/utils/theme.ts,其中的代码为:

const darkThemeSwitch = () => {
    // id要与前面一致
    const theme_element = document.querySelector('#dark-theme-style');
    if (!theme_element) {
        const new_dark_Theme = document.createElement('link')
        new_dark_Theme.setAttribute('rel', 'stylesheet');
        //刚刚设置的css路径
        new_dark_Theme.setAttribute('href', '/styles/dark.css');
        // id可以自由设置
        new_dark_Theme.setAttribute('id', 'dark-theme-style');
        const docHead = document.querySelector('head');
        docHead?.append(new_dark_Theme);
    } else {
        const parentNode = theme_element?.parentNode;
        parentNode?.removeChild(theme_element);
    }
}

export default darkThemeSwitch;

3. 切换主题

然后,我们在需要切换主题的地方使用这个方法就可以了:

<template>
    <a-button @click="toggleDark">切换主题</a-button>
</template>

<script setup lang="ts">
    import darkThemeSwitch from '../utils/theme';
    const toggleDark = () => {
        darkThemeSwitch();
    };
</script>

Quasar 的方式

quasar 的主题切换非常简单,只要使用 quasar 官方提供的 dark 插件就可以了,使用方法如下:

import { useQuasar } from 'quasar'
const $q = useQuasar()

// get status
console.log($q.dark.isActive) // true, false

// get configured status
console.log($q.dark.mode) // "auto", true, false

// set status
$q.dark.set(true) // or false or "auto"

// toggle
$q.dark.toggle()

通过研究 Quasar 的源码,可以发现,Quasar 的黑暗有两种设置方式,自动和手动,在自动模式下,插件通过监听 prefers-color-scheme: dark 的状态来决定当前网页的主题,通过这种方式,可以实现网页跟随系统主题自动变换浅色和深色模式,对应部分的代码如下:

Plugin.mode = val
if (val === 'auto') {
  if (Plugin.__media === void 0) {
    Plugin.__media = window.matchMedia('(prefers-color-scheme: dark)')
    Plugin.__updateMedia = () => { Plugin.set('auto') }
    Plugin.__media.addListener(Plugin.__updateMedia)
  }

  val = Plugin.__media.matches
}

上面的代码中,Plugin.mode 代表设置方式,Plugin.__media 的值默认就是 void 0,这里的判断的作用是当第一次执行时给相应的 Media 添加一个监听来获得实时的变化。这里调用的 Plugin.set('auto') 就是手动设置的函数,这个函数接受一个布尔值,然后根据布尔值的真假对主题进行设置,相应的实现如下:

document.body.classList.remove(`body--${ val === true ? 'light' : 'dark' }`)
document.body.classList.add(`body--${ val === true ? 'dark' : 'light' }`)

显然,这里的实现方式也比较常规,即在 body 标签添加或删除相应的样式选择器类名来实现主题的切换,quasar 值得我们学习的地方在于它把所有的功能集成到 useQuasar 中,用户可以方便地使用各种插件,而不需要写很多代码。完整的代码如下:

import defineReactivePlugin from '../utils/private/define-reactive-plugin.js'
import { isRuntimeSsrPreHydration } from './Platform.js'

const Plugin = defineReactivePlugin({
    // 插件的属性
    isActive: false,
    mode: false
}, {
    __media: void 0,
    // 插件的核心方法
    set(val) {
        if (__QUASAR_SSR_SERVER__) { return }

        Plugin.mode = val
        // 自动主题切换
        if (val === 'auto') {
            if (Plugin.__media === void 0) {
                Plugin.__media = window.matchMedia('(prefers-color-scheme: dark)')
                Plugin.__updateMedia = () => { Plugin.set('auto') }
                Plugin.__media.addListener(Plugin.__updateMedia)
            }

            val = Plugin.__media.matches
        }
        else if (Plugin.__media !== void 0) {
            Plugin.__media.removeListener(Plugin.__updateMedia)
            Plugin.__media = void 0
        }

        Plugin.isActive = val === true
        // 手动指定主题
        document.body.classList.remove(`body--${val === true ? 'light' : 'dark'}`)
        document.body.classList.add(`body--${val === true ? 'dark' : 'light'}`)
    },
    // 主题的切换
    toggle() {
        if (__QUASAR_SSR_SERVER__ !== true) {
            Plugin.set(Plugin.isActive === false)
        }
    },

    install({ $q, onSSRHydrated, ssrContext }) {
        const { dark } = $q.config

        if (__QUASAR_SSR_SERVER__) {
            this.isActive = dark === true

            $q.dark = {
                isActive: false,
                mode: false,
                set: val => {
                    ssrContext._meta.bodyClasses = ssrContext._meta.bodyClasses
                        .replace(' body--light', '')
                        .replace(' body--dark', '') + ` body--${val === true ? 'dark' : 'light'}`

                    $q.dark.isActive = val === true
                    $q.dark.mode = val
                },
                toggle: () => {
                    $q.dark.set($q.dark.isActive === false)
                }
            }

            $q.dark.set(dark)
            return
        }

        $q.dark = this

        if (this.__installed === true && dark === void 0) {
            return
        }

        this.isActive = dark === true

        const initialVal = dark !== void 0 ? dark : false

        if (isRuntimeSsrPreHydration.value === true) {
            const ssrSet = val => {
                this.__fromSSR = val
            }

            const originalSet = this.set

            this.set = ssrSet
            ssrSet(initialVal)

            onSSRHydrated.push(() => {
                this.set = originalSet
                this.set(this.__fromSSR)
            })
        }
        else {
            this.set(initialVal)
        }
    }
})

export default Plugin

ElementUI 的方式

在 2.2.0 版本,Element UI 也可以进行黑暗模式切换了,操作如下:

  • 在 main.ts 引入官方的 CSS:import 'element-plus/theme-chalk/dark/css-vars.css'

更改 html 标签的类,添加 dark 即为黑暗模式,去掉 dark 即为明亮模式,这一过程有很多实现方法,官方推荐使用 VueUse 这个函数库中的 useDark 来实现,这是一个非常强大的官方工具库,里面提供了许多常用功能的实现以及一些小插件,非常值得学习,请参考VueUse的官方文档:

<template>
    <el-button @click="toggleDark()">切换主题</el-button>
</template>

<script setup lang="ts">
    import { useDark, useToggle } from '@vueuse/core';

    const isDark = useDark();
    const toggleDark = useToggle(isDark);
</script>

NaiveUI 的方式

NaiveUI 的黑暗主题是通过其提供的 Config Provider 组件来实现的,通过设置其 theme 属性为 null 或者 darkTheme(需要从 naive-ui 导入),可以更改其内部组件的主题,配合 Global Style 组件,可以设置全局的主题:

<template>
  <n-config-provider :theme="theme">
    <n-card>
      <n-space>
        <n-button @click="theme = darkTheme">
          深色
        </n-button>
        <n-button @click="theme = null">
          浅色
        </n-button>
      </n-space>
    </n-card>
    <!-- 加上这个后可以切换全局主题 -->
    <n-global-style />
  </n-config-provider>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { darkTheme } from 'naive-ui'
import type { GlobalTheme } from 'naive-ui'

const theme = ref<GlobalTheme | null>(null)
</script>

还可以通过 useOsTheme 获取系统的主题作为组件的主题:

<template>
  <n-config-provider :theme="theme">
    <n-card> 当前操作系统的主题是 {{ osTheme }}。 </n-card>
  </n-config-provider>
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue'
import { useOsTheme, darkTheme } from 'naive-ui'

export default defineComponent({
  setup () {
    const osThemeRef = useOsTheme()
    return {
      theme: computed(() => (osThemeRef.value === 'dark' ? darkTheme : null)),
      osTheme: osThemeRef
    }
  }
})
</script>

让我们来看一下它的实现,好吧,我水平实在是有限,真的看不懂,但是看起来真的很厉害。

到此这篇关于Vue UI框架的主题切换功能实现的文章就介绍到这了,更多相关vue主题切换内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用vue-antd动态切换主题

    目录 vue-antd动态切换主题 安装依赖 Vue3.0 + Antd,修改antd主题色,配置全局css vue-antd动态切换主题 安装依赖 1 webpack-theme-color-replacer: yarn add webpack-theme-color-replacer@1.3.22 2 less: yarn add less@2.7.2 3 less-loader: yarn add less-loader@7.0.2 在vue.config.js中加入配置 const cr

  • vue实现主题切换的多种思路分享

    动态改变主题 首先需要解决的是如何知道你需要显示哪个主题,并且可以动态切换.我选择的方法是queryString. 我们打开url的时候,可以在后面缀上?theme=xx,读取这个xx储存起来即可. 第一种办法:动态组件 当主题的路由并没有发生变化,仅是组件内部的样式,功能发生了变化,我们可以将一个组件复制一遍,修改完后,通过懒加载和动态组件实现. // 页面组件 <template> <div> <component :is="themeName" /&

  • vue在线动态切换主题色方案

    主要原理是利用webpack插件webpack-theme-color-replacer提取相关颜色css然后根据配置动态生成替换的css 具体实现步骤如下: 1.添加webpack插件,新建文件webpack/themePlugin.js const ThemeColorReplacer = require('webpack-theme-color-replacer') const forElementUI = require('webpack-theme-color-replacer/for

  • 基于Vue2.0和Typescript实现多主题切换的示例

    目录 第一步: 需要创建一个colorConfig.ts文件,用于配置主题信息 (我创建的目录是src/config/colorConfig.ts) 第二步,根据接口获取当前主题信息,并进行切换设置 第三步,切换主题时,更新缓存 第四步, 页面上使用css变量来动态展示颜色值 之前在项目中用了Sass的多主题切换,感觉太麻烦,后面发现直接用CSS的很方便,所以整理一下,希望可以帮到大家,也是对自己的积累. 第一步: 需要创建一个colorConfig.ts文件,用于配置主题信息 (我创建的目录是

  • Vue + Scss 动态切换主题颜色实现换肤的示例代码

    根据预设的配色方案,在前端实现动态切换系统主题颜色. 大概的思路就是给html根标签设置一个data-theme属性,然后通过js切换data-theme的属性值,Scss根据此属性来判断使用对应主题变量.这里可以选择持久化Vux或接口来保存用户选择的主题. 一.首先需要给项目下载配置Scss 1.安装依赖 npm install node-sass sass-loader --save-dev 2.找到build中webpack.base.conf.js,在rules中添加scss规则 { t

  • vue+element-ui实现主题切换功能

    element-ui提供了自定义主题 自定义主题 一.安装 npm i element-theme -g npm i element-theme-chalk -D npm i https://github.com/ElementUI/theme-chalk -D 官网说明安装完成后需要et -i并会有element-variables.scss文件,但是我文件中并未找到 node_modules/.bin/et,所以手动生成了 下图element-variables.scss是自己写的,因为安装

  • VUE项目实现主题切换的多种方法

    需求是 做一个深色主题和浅色主题切换的效果 方法一 多套css 这个方法也是最简单,也是最无聊的. <!-- 中心 --> <template> 动态获取父级class名称,进行一个父级class的多次定义 <div :class="className"> <div class="switch" v-on:click="chang()"> {{ className == "box"

  • vue实现密码显示隐藏切换功能

    先给大家分享效果图: 具体实现代码如下所示: html: <group> <span>设置密码</span> <x-input :type="this.registration_data.pwdType" placeholder="请填写密码" @on-change="password"></x-input> <img :src="this.registration_da

  • 利用Jetpack Compose实现主题切换功能

    目录 前言 color.kt Theme.kt 关于compositionLocalOf 完整代码 前言 新建的Compose项目默认的 Material 主题为我们提供了一些颜色,但对我这种花里胡哨的人来说根本不够呀. 所以系统提供的主题不能满足需求时候可以自己配置主题 compose 实现换肤很简单 之前xml方法可复杂了 通过LayoutInflater调用inflate方法加载XML布局,在inflate方法中有一个createViewFromTag,再根据LayoutInflater当

  • Android主题切换之探究白天和夜间模式

    智能手机的迅速普及,大大的丰富了我们的娱乐生活.现在大家都喜欢晚上睡觉前玩会儿手机,但是应用的日间模式往往亮度太大,对眼睛有较为严重的伤害.因此,如今的应用往往开发了 日间和夜间 两种模式供用户切换使用,那日间和夜间模式切换究竟是怎样实现的呢? 在文字类的App上面基本上都会涉及到夜间模式.就是能够根据不同的设定.呈现不同风格的界面给用户.而且晚上看着不伤眼睛.实现方式也就是所谓的换肤(主题切换).对于夜间模式的实现网上流传了很多种方式.这里先分享一个方法给大家.通过设置背景为透明的方法.降低屏

  • iOS开发之App主题切换解决方案完整版(Swift版)

    本篇博客就来介绍一下iOS App中主题切换的常规做法,当然本篇博客中只是提到了一种主题切换的方法,当然还有其他方法,在此就不做过多赘述了.本篇博客中所涉及的Demo完全使用Swift3.0编写完成,并使用iOS的NSNotification来触发主题切换的动作.本篇博客我们先对我们的主题系统进行设计,然后给出具体实现方式.当然在我们设计本篇博客所涉及的Demo时,我们要遵循"高内聚,低耦合","面向接口编程","便于维护与扩充"等特点. 本篇博

  • vue移动端UI框架实现QQ侧边菜单组件

    最近面试发现很多前端程序员都从来没有写过插件的经验,基本上都是网上百度.所以打算写一系列文章,手把手的教一些没有写过组件的兄弟们如何去写插件.本系列文章都基于VUE,核心内容都一样,会了之后大家可以快速的改写成react.angular或者是小程序等组件.这篇文章是第一篇,写的是一个类似QQ的侧边菜单组件. 效果展示 先让大家看个效果展示,知道咱们要做的东西是个怎么样的样子,图片有点模糊,大家先将就点: 开始制作 DOM结构 整体结构中应该存在两个容器:1. 菜单容器 2. 主页面容器:因此当前

  • react实现antd线上主题动态切换功能

    demo 框架选择: create-react-app + mobx + webpack5 + antdesign 说明 由于最近公司有多个主题的共存性,所以需要实现线上主题切换的功能,所以本文主要描述的是基于create-react-app之上的主题切换. CSS切换 有考虑过根据用户选择的主题在切换的时候选择加载页面css文件的区分方案,但是考虑到这种形式需要在页面切换的时候去reload,因为htmlDOM是在css与JS的结合产物,用户体验不是很好. Less切换 单纯引入所有的less

  • 浅谈Vue CLI 3结合Lerna进行UI框架设计

    当前大部分UI框架设计的Webpack配置都相对复杂,例如 Element. Ant Design Vue和Muse-UI等Vue组件库.例如Element,为了实现业务层面的两种引入形式( 完整引入 和 按需引入 ),以及抛出一些可供业务层面通用的 utils . i18n 等,Webpack配置变得非常复杂.为了简化UI框架的设计难度,这里介绍一种简单的UI框架设计,在此之前先简单介绍一下 Element 的构建流程,以便对比新的UI框架设计. 一般组件库的设计者将引入形式设计成 完整引入

  • 基于 Vue.js 之 iView UI 框架非工程化实践记录(推荐)

    像我们平日里做惯了 Java 或者 .NET 这种后端程序员,对于前端的认识还常常停留在 jQuery 时代,包括其插件在需要时就引用一下,不需要就删除.故观念使然,尽管 Nuget 和 Maven 用得顺溜,但对 NPM 仍不带感,兴许是周边无人带动的稀薄气氛,也或者是没参加过类似的大型活动,于是在自发性上差了许多.再者,我不用 MVVM 模式,领导也不会扣绩效. 为了快速体验 MVVM 模式,我选择了非工程化方式来起步,并选择使用 Vue.js,以及基于它构建的 iView UI 框架. V

  • Vue中使用vue-i18插件实现多语言切换功能

    在基于vue-cli项目开发过程中,多语言切换功能可使用vue-i18插件,具体实现方法如下: step1: 在项目中安装vue-i18插件 cnpm install vue-i18n --save-dev step2:在项目的入口文件main.js中引入vue-i18n插件  import Vue from 'vue' import router from './router' import VueI18n from 'vue-i18n' Vue.use(VueI18n) const i18n

随机推荐