vue實(shí)現(xiàn)主題切換的多種思路分享
動(dòng)態(tài)改變主題
首先需要解決的是如何知道你需要顯示哪個(gè)主題,并且可以動(dòng)態(tài)切換。我選擇的方法是queryString。
我們打開(kāi)url的時(shí)候,可以在后面綴上?theme=xx,讀取這個(gè)xx儲(chǔ)存起來(lái)即可。
第一種辦法:動(dòng)態(tài)組件
當(dāng)主題的路由并沒(méi)有發(fā)生變化,僅是組件內(nèi)部的樣式,功能發(fā)生了變化,我們可以將一個(gè)組件復(fù)制一遍,修改完后,通過(guò)懶加載和動(dòng)態(tài)組件實(shí)現(xiàn)。
// 頁(yè)面組件 <template> <div> <component :is="themeName" /> </div> </template> <script> export default{ name: 'Home', components:{ theme1:()=>import('@/theme/theme1/a'), theme2:()=>import('@/theme/theme2/a'), }, computed:{ themeName(){ retun `theme${this.$store.state.themeId}` } } } </script>
在組件中,我將script部分抽離出來(lái),因?yàn)榇蟛糠纸M件其實(shí)在邏輯上是相同。哪怕有一些不同,我們也可以直接在主題2的組件中更改,減少對(duì)主題1的影響。
//action.js export default{ name:'Theme1', .... } <template> <div class="theme1"></div> </template> <script> import action from '../componentAction/action' action.name='Theme1' export default action </script> <style scoped> </style>
這樣實(shí)現(xiàn)的有點(diǎn)是可以通過(guò)子組件的style scoped實(shí)現(xiàn)樣式隔離,同時(shí)功能數(shù)據(jù)上都會(huì)隔離,例如兩個(gè)子組件中的swiper不會(huì)相互影響。 同時(shí),懶加載也減小了首頁(yè)的加載時(shí)體積。 后面再增加新增的主題也只是照貓畫(huà)虎而已。
第二種辦法,路由隔離
路由隔離其實(shí)就是簡(jiǎn)單的theme1寫(xiě)一個(gè)路由的數(shù)組,theme2寫(xiě)一套路由。
// router.js { path:'/theme3', name:'theme3Index', component: () => import('../views/theme3/Index.vue'), children:[ { path: '/theme3/entry', name: 'theme3Entry', component: () => import('../views/theme3/entry.vue'), } ] }
這種辦法其實(shí)是下下之策,我使用這個(gè)主要是因?yàn)槁酚勺兓?,比如之前是直接進(jìn)入a.vue,但是現(xiàn)在前面多加了一層entry頁(yè)面,所以只能改變路由。 這種辦法也實(shí)現(xiàn)了比較好的隔離。
總結(jié)
以上兩種思路是我針對(duì)于我們當(dāng)前業(yè)務(wù)的思考,僅供參考。
其實(shí)這兩種方法都有一個(gè)共同的問(wèn)題,就是代碼冗余。每個(gè)組件都避不可免的帶有一部分之前主題的代碼,雖然,大部分邏輯代碼可以抽離出來(lái),但是css和template卻無(wú)法抽離。
如果每次一個(gè)主題增加一個(gè)dom,一個(gè)功能塊,如果每次都用v-if,那么其實(shí)代碼以后會(huì)更加難以維護(hù)。因此,我選擇了按照主題去劃分代碼。
額外補(bǔ)充基于css的兩種方法
方法一 多套css
<!-- 中心 --> <template> 動(dòng)態(tài)獲取父級(jí)class名稱(chēng),進(jìn)行一個(gè)父級(jí)class的多次定義 <div :class="className"> <div class="switch" v-on:click="chang()"> {{ className == "box" ? "開(kāi)燈" : "關(guān)燈" }} </div> </div> </template> <script> export default { name: "Centre", data() { return { className: "box" }; }, methods: { // 改變class chang() { this.className === "box" ? (this.className = "boxs") : (this.className = "box"); } }, }; </script> <style lang="scss"> 當(dāng)class為box 使用witch的css @import "./style/witch.scss"; 當(dāng)class為boxs 使用black的css @import "./style/black.scss"; .switch { position: fixed; top: 4px; right: 10px; z-index: 50; width: 60px; height: 60px; background: #fff; line-height: 60px; border-radius: 20%; } </style>
每個(gè)css文件樣式大致相同,只是最外層的父級(jí)不一樣,分別為.box 和.boxs
方法二 scss動(dòng)態(tài)切換變量
我自己是分為了2個(gè)主要文件來(lái)做的
- _variable.scss 變量管理文件
- var()為css3中提出的聲明樣式變量的方法
- var(屬性名,屬性值)注意屬性值不能是字符串
// 主題切換 $bgColor:var(--backgroundColor,rgb(255,255,255)); $fontColor:var(--fonntColor,rgb(0,0,0)); $bgmColor:var(--backgroundMColor,rgb(238,238,238)); $tableColor:var(--tableColor,rgb(218,218,218)); $borderColor:var(--borderColor,rgb(238,238,238)); $tablesColor:var(--tablesColor,rgb(255,255,255)); $inputColor:var(--inputColor,rgb(255,255,255))
創(chuàng)建的_variable.scss 文件我在vue.config.js進(jìn)行了一個(gè)全局的配置,沒(méi)有在組件中引入
css: { loaderOptions: { // 此文件為主題切換文件 sass: { prependData: `@import "./src/styles/_variable.scss";`, }, }, },
publicStyle.js
這個(gè)方法可以去修改var定義的變量
document.getElementsByTagName("body")[0].style.setProperty("屬性名", "替換的屬性值f");
// 主題切換 const cut = (cutcheack) => { document.getElementsByTagName("body")[0].style.setProperty("--backgroundColor", cutcheack ? "#121212" : "#fff"); document.getElementsByTagName("body")[0].style.setProperty("--fonntColor", cutcheack ? "#cecece" : "#333"); document.getElementsByTagName("body")[0].style.setProperty("--backgroundMColor", cutcheack ? "#333" : "#eee"); document.getElementsByTagName("body")[0].style.setProperty("--tableColor", cutcheack ? "#000" : "#d8d8d8"); document.getElementsByTagName("body")[0].style.setProperty("--tablesColor", cutcheack ? "#222" : "#fff"); document.getElementsByTagName("body")[0].style.setProperty("--inputColor", cutcheack ? "#666" : "#fff"); document.getElementsByTagName("body")[0].style.setProperty("--borderColor", cutcheack ? "#666" : "#fff"); }; export default cut;
組件中使用
<!-- 首頁(yè) --> <template> <div class='home'> <el-switch v-model="cutcheack" active-color="#333" inactive-color="#13ce66" active-text="主題" @change="switchs"></el-switch> </div> </template> <script> import cut from "../../utils/publicStyle.js"; export default { name: "Home", data() { return { cutcheack: false, //主題切換 }; }, methods: { // 左側(cè)導(dǎo)航隱藏或顯示 // 切換主題 switchs() { cut(this.cutcheack); }, }, }; </script> <style lang='scss' scope> .home { height: 100%; width: 100%; background:$bgColor; .el-container { height: 100%; color:$fontColor; } } </style>
以上就是vue實(shí)現(xiàn)主題切換的多種思路分享的詳細(xì)內(nèi)容,更多關(guān)于vue 主題切換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue+moment實(shí)現(xiàn)倒計(jì)時(shí)效果
這篇文章主要為大家詳細(xì)介紹了vue+moment實(shí)現(xiàn)倒計(jì)時(shí)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08Vue項(xiàng)目中如何封裝axios(統(tǒng)一管理http請(qǐng)求)
這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中如何封裝axios(統(tǒng)一管理http請(qǐng)求)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05詳解mpvue scroll-view自動(dòng)回彈bug解決方案
設(shè)置了scroll-top的scroll-view組件,在組件所在vue實(shí)例data發(fā)生改變時(shí)會(huì)自動(dòng)回彈到最上方,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-10-10javascript中Set、Map、WeakSet、WeakMap區(qū)別
這篇文章主要介紹了javascript中Set、Map、WeakSet、WeakMap區(qū)別,需要的朋友可以參考下2022-12-12vue3+vite使用vite-plugin-svg-icons插件顯示本地svg圖標(biāo)的方法
這篇文章主要介紹了vue3+vite使用vite-plugin-svg-icons插件顯示本地svg圖標(biāo)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-12-12vue3源碼剖析之簡(jiǎn)單實(shí)現(xiàn)方法
源碼的重要性相信不用再多說(shuō)什么了吧,特別是用Vue 框架的,一般在面試的時(shí)候面試官多多少少都會(huì)考察源碼層面的內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于vue3源碼剖析之簡(jiǎn)單實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2021-09-09