Vue?UI框架的主題切換功能實(shí)現(xiàn)
在如今,很多網(wǎng)頁(yè)已經(jīng)可以手動(dòng)切換明亮模式和黑暗模式,網(wǎng)頁(yè)的主題切換已經(jīng)成為了一個(gè)常用的需求,因此,本文將從常見(jiàn)框架的處理方式總結(jié)一些相關(guān)的操作,并探究其本質(zhì)。
AntD 的方式
AntD 的 config-provider 似乎不能直接修改主題,目前網(wǎng)絡(luò)上的教程有兩類,一類是通過(guò) less 的修改變量修改來(lái)完成,另一類是操作 DOM 改變對(duì)文件的引用,由于 ant-design-vue 已經(jīng)提供了黑暗主題,而且直接修改 less 文件的變量涉及到了太多變量,不太方便,因此參考了這篇文章vue3點(diǎn)擊出現(xiàn)彈窗后背景變暗且不可操作的實(shí)現(xiàn)代碼,使用動(dòng)態(tài)添加 CSS 引用 DOM 的方式實(shí)現(xiàn)黑暗主題的切換,原理是添加一個(gè) DOM,引用我們自定義的 CSS 樣式,后面的引用會(huì)覆蓋前面的引用,在切換到亮色主題時(shí)把這個(gè) DOM 刪除。
1. 創(chuàng)建黑暗主題文件
在目錄下的適當(dāng)位置創(chuàng)建一個(gè)黑暗主題的文件,后面要引用這個(gè)文件,這里直接把官方黑暗主題復(fù)制過(guò)來(lái)就可以了,它的位置在 node_modules\ant-design-vue\dist\antd.dark.min.css,假設(shè)我們把它復(fù)制到了 public/styles/dark.css 中。
2. 創(chuàng)建切換主題的函數(shù)
有了主題文件,我們就可以創(chuàng)建切換主題的函數(shù)了,在目錄中的合適位置創(chuàng)建一個(gè) 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');
//剛剛設(shè)置的css路徑
new_dark_Theme.setAttribute('href', '/styles/dark.css');
// id可以自由設(shè)置
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. 切換主題
然后,我們?cè)谛枰袚Q主題的地方使用這個(gè)方法就可以了:
<template>
<a-button @click="toggleDark">切換主題</a-button>
</template>
<script setup lang="ts">
import darkThemeSwitch from '../utils/theme';
const toggleDark = () => {
darkThemeSwitch();
};
</script>Quasar 的方式
quasar 的主題切換非常簡(jiǎn)單,只要使用 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()通過(guò)研究 Quasar 的源碼,可以發(fā)現(xiàn),Quasar 的黑暗有兩種設(shè)置方式,自動(dòng)和手動(dòng),在自動(dòng)模式下,插件通過(guò)監(jiān)聽(tīng) prefers-color-scheme: dark 的狀態(tài)來(lái)決定當(dāng)前網(wǎng)頁(yè)的主題,通過(guò)這種方式,可以實(shí)現(xiàn)網(wǎng)頁(yè)跟隨系統(tǒng)主題自動(dòng)變換淺色和深色模式,對(duì)應(yīng)部分的代碼如下:
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 代表設(shè)置方式,Plugin.__media 的值默認(rèn)就是 void 0,這里的判斷的作用是當(dāng)?shù)谝淮螆?zhí)行時(shí)給相應(yīng)的 Media 添加一個(gè)監(jiān)聽(tīng)來(lái)獲得實(shí)時(shí)的變化。這里調(diào)用的 Plugin.set('auto') 就是手動(dòng)設(shè)置的函數(shù),這個(gè)函數(shù)接受一個(gè)布爾值,然后根據(jù)布爾值的真假對(duì)主題進(jìn)行設(shè)置,相應(yīng)的實(shí)現(xiàn)如下:
document.body.classList.remove(`body--${ val === true ? 'light' : 'dark' }`)
document.body.classList.add(`body--${ val === true ? 'dark' : 'light' }`)顯然,這里的實(shí)現(xiàn)方式也比較常規(guī),即在 body 標(biāo)簽添加或刪除相應(yīng)的樣式選擇器類名來(lái)實(shí)現(xiàn)主題的切換,quasar 值得我們學(xué)習(xí)的地方在于它把所有的功能集成到 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
// 自動(dòng)主題切換
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
// 手動(dòng)指定主題
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 也可以進(jìn)行黑暗模式切換了,操作如下:
在
main.ts引入官方的 CSS:import 'element-plus/theme-chalk/dark/css-vars.css'
更改 html 標(biāo)簽的類,添加 dark 即為黑暗模式,去掉 dark 即為明亮模式,這一過(guò)程有很多實(shí)現(xiàn)方法,官方推薦使用 VueUse 這個(gè)函數(shù)庫(kù)中的 useDark 來(lái)實(shí)現(xiàn),這是一個(gè)非常強(qiáng)大的官方工具庫(kù),里面提供了許多常用功能的實(shí)現(xiàn)以及一些小插件,非常值得學(xué)習(xí),請(qǐng)參考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 的黑暗主題是通過(guò)其提供的 Config Provider 組件來(lái)實(shí)現(xiàn)的,通過(guò)設(shè)置其 theme 屬性為 null 或者 darkTheme(需要從 naive-ui 導(dǎo)入),可以更改其內(nèi)部組件的主題,配合 Global Style 組件,可以設(shè)置全局的主題:
<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>
<!-- 加上這個(gè)后可以切換全局主題 -->
<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>還可以通過(guò) useOsTheme 獲取系統(tǒng)的主題作為組件的主題:
<template>
<n-config-provider :theme="theme">
<n-card> 當(dāng)前操作系統(tǒng)的主題是 {{ 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>讓我們來(lái)看一下它的實(shí)現(xiàn),好吧,我水平實(shí)在是有限,真的看不懂,但是看起來(lái)真的很厲害。
到此這篇關(guān)于Vue UI框架的主題切換功能實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue主題切換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue props 單項(xiàng)數(shù)據(jù)流實(shí)例分享
在本篇文章里小編給大家分享的是一篇關(guān)于vue props 單項(xiàng)數(shù)據(jù)流實(shí)例分享內(nèi)容,需要的朋友們可以參考下。2020-02-02
vue單頁(yè)面應(yīng)用打開(kāi)新窗口顯示跳轉(zhuǎn)頁(yè)面的實(shí)例
今天小編就為大家分享一篇vue單頁(yè)面應(yīng)用打開(kāi)新窗口顯示跳轉(zhuǎn)頁(yè)面的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
Vue2.0實(shí)現(xiàn)簡(jiǎn)單分頁(yè)及跳轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了Vue2.0實(shí)現(xiàn)簡(jiǎn)單數(shù)據(jù)分頁(yè),及頁(yè)數(shù)的跳轉(zhuǎn)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
vue打印瀏覽器頁(yè)面功能的兩種實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于vue打印瀏覽器頁(yè)面功能的兩種實(shí)現(xiàn)方法,這個(gè)功能其實(shí)也是自己學(xué)習(xí)到的,做完也有一段時(shí)間了,一直想記錄總結(jié)一下,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04
Vue滑塊驗(yàn)證碼組件anji-captcha的使用案例詳解
滑塊驗(yàn)證是一種常見(jiàn)的人機(jī)識(shí)別方法,這篇文章主要介紹了Vue滑塊驗(yàn)證碼組件anji-captcha的使用,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
Vue中響應(yīng)式系統(tǒng)實(shí)現(xiàn)原理圖文講解
Vue的響應(yīng)式實(shí)現(xiàn)是借助Object.defineProperty通過(guò)重寫getter和setter方法來(lái)進(jìn)行的數(shù)據(jù)劫持,Vue3通過(guò)Proxy代理攔截對(duì)象中任意屬性的變化,通過(guò)Reflect反射對(duì)源對(duì)象的屬性進(jìn)行操作,然后再在get里收集依賴在set里派發(fā)更新2023-03-03
antd vue表格可編輯單元格以及求和實(shí)現(xiàn)方式
這篇文章主要介紹了antd vue表格可編輯單元格以及求和實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Vue-input框checkbox強(qiáng)制刷新問(wèn)題
這篇文章主要介紹了Vue-input框checkbox強(qiáng)制刷新問(wèn)題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04
Vue3.x+Element Plus仿制Acro Design簡(jiǎn)潔模式實(shí)現(xiàn)分頁(yè)器組件
開(kāi)發(fā)中難免會(huì)遇到寬度很窄的列表需要使用分頁(yè)器的情況。本文將利用Vue3.x+Element Plus仿制Acro Design簡(jiǎn)潔模式實(shí)現(xiàn)分頁(yè)器組件,感興趣的可以了解一下2023-02-02
使用vue.js寫一個(gè)tab選項(xiàng)卡效果
Vue 實(shí)現(xiàn) Tab切換實(shí)現(xiàn)的場(chǎng)景很多,比如,利用vue-router、利用第三方插件、利用組件等等.本文使用組件來(lái)實(shí)踐tab選項(xiàng)卡2017-03-03

