溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

vue中如何實現(xiàn)一個換膚功能

發(fā)布時間:2022-04-28 16:40:19 來源:億速云 閱讀:253 作者:iii 欄目:大數(shù)據(jù)

這篇“vue中如何實現(xiàn)一個換膚功能”文章的知識點大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“vue中如何實現(xiàn)一個換膚功能”文章吧。

1 色值的選取和原則

對于界面中的色彩元素,我們一般要保持視覺的連續(xù)性,即同一套色彩,盡量采取同一個色環(huán)上的色值

vue中如何實現(xiàn)一個換膚功能 

同一個圓環(huán)上的色值作為一套顏色會顯得更協(xié)調(diào)

所以這里采取ant design 的建議,取某一列色值作為我們的系列主題顏色(具體色值參照它的官網(wǎng)吧~)

vue中如何實現(xiàn)一個換膚功能 

而在某些特殊場合,需要表現(xiàn)出顏色的差異,如拋硬幣頁面的兩個顏色,

vue中如何實現(xiàn)一個換膚功能 

2 將格式色值轉(zhuǎn)換成十六進(jìn)制顏色值

這里我們通過設(shè)置主題顏色的透明度來實現(xiàn)區(qū)分不同顏色, 然后我們是通過存儲一個諸如 #123456 的16進(jìn)制顏色全局變量作為我們主題,這里就需要我們把這樣一個格式的色值轉(zhuǎn)化成 rgba 表示的顏色值啦,代碼如下,備用

hexToRgba (hex, opacity = 0.3) {
  let color = []
  let rgb = []
  hex = hex.replace(/#/, '')
  for (let i = 0; i < 3; i++) {
   color[i] = '0x' + hex.substr(i * 2, 2)
   rgb.push(parseInt(Number(color[i])))
  }
  return `rgba(${rgb.join(',')},${opacity})`
 }

3 scss 的一些小眾用法

我們最終拿到這么一串我們想要的主題顏色

復(fù)制代碼 代碼如下:


$colors: #f04134, #00a854, #108ee9, #f5317f, #f56a00, #7265e6, #ffbf00, #00a2ae, #2e3238;

一個很直接的思路,我們需要在各個view頁面里面,去定義我們需要設(shè)置主題的元素的顏色,比如文字和icon的color, 以及頭部的background 等。 于是我們在app 里面定義一個color變量,派發(fā)到各個view組件里面去,通過這個全局的變量來控制所有路由頁面的顏色,以實現(xiàn)不同的主題效果。

派發(fā)的實現(xiàn)在下一個部分說,這里我們先來完成我們的第一步,我們可以容易提取出我們的需求:

4 設(shè)置并保存一個全局顏色

界面的小事:

我在首頁直接實現(xiàn)這個功能,項目中我引入了mint-ui 框架(餓了么團(tuán)隊的移動端框架,稍微遺憾使用感覺沒有element.ui 的舒服), 設(shè)置的交互就用彈層 mt-popup 的形式好了,然后直接點擊色塊便設(shè)置對應(yīng)顏色值

<!-- 設(shè)置顏色 -->
  <mt-popup v-model="changColor" position="bottom" class="color-panel">
   <div class="color-items">
     <span class="color-item" v-for="(item, $index) in colors" :key="$index" @click="chooseColor(item)">
      <span class="color-cycle" :class="'bg-color' + ($index + 1)"></span>
      </span>
   </div>
  </mt-popup>

接著就是色塊div的呈現(xiàn),從上面代碼發(fā)現(xiàn),我會很容易出現(xiàn)類似這樣的css樣式表

.bg-color1 {background: #f04134}
.bg-color2 {background: #f04134}
.bg-color3 {background: #f04134}
.bg-color4 {background: #f04134}
···

寫代碼時候如果我們一般發(fā)現(xiàn),一件類似的東西重復(fù)出現(xiàn)了,就總隱隱覺得可以開始表演了,然后可預(yù)見的是,這樣的情況意味著在項目增長后,還可能出現(xiàn)許多單一設(shè)置字體顏色或border顏色的樣式表,諸如color1, borderColor1···,這樣每種形式的表現(xiàn)我們都需要根據(jù)我們主題顏色的數(shù)組去逐條書寫,修改成本也會變高 。于是我的書寫風(fēng)格是這樣的,

// mixin.scss:
$colors: #f04134, #00a854, #108ee9, #f5317f, #f56a00, #7265e6, #ffbf00, #00a2ae, #2e3238;

// setColor.vue:
@import '~@/assets/mixin.scss';
···
@for $i from 1 to 10 {
    .bg-color#{$i} {
     background-color: nth($colors, $i)
    }
   }

scss 除了常用的類名嵌套書寫外,還有許多···低調(diào)奢華的語法, 對于這類需要重復(fù)書寫的樣式類型,我的約定是添加一個scss變量在mixin 文件中, 在需要書寫重復(fù)循環(huán)樣式時候作為變量引入,并在書寫樣式時候,利用sass的循環(huán),引用其中對應(yīng)的值,這樣無論設(shè)置顏色的樣式怎么拓展和變化,變成顏色背景邊框都好,我都只需要維護(hù)一份mixin的的文件里的色值就行了, 同樣的實踐也可以應(yīng)用于項目里面字體大小和間距值的統(tǒng)一之類,總之我們多嘗試體驗下吧

5 邏輯的小事

這個項目里面localstorage 基本被當(dāng)成數(shù)據(jù)庫使用了,所以點擊色塊設(shè)置主題時候,我們假裝發(fā)出請求,在localstorage存儲我們改變的顏色就好了( ./static/api.json 是一個返回helloword 的json, 為了寫實在這里這么用,$bus 事件巴士下面說, 作用就是設(shè)置全局的主題顏色變量,localStorage 模擬我們把設(shè)置存儲到后臺,每次重新打開頁面就去獲取這些設(shè)置值), 目前為止,我們的設(shè)置頁面就大致完成了

// 假裝調(diào)用接口設(shè)置顏色
  chooseColor (color) {
   this.$axios.get('./static/api.json')
    .then((data) => {
     this.$bus.$emit('set-theme', color)
     this.changColor = false
     localStorage.setItem('themeColor', color)
    })
    .catch((data) => {
     console.log(data)
    })
  }

6 事件巴士的運(yùn)用

在上一步最后我們有個關(guān)鍵的東西沒完成, this.$bus.$emit('set-theme', color) ,將選取的顏色設(shè)置到全局,我的代碼結(jié)構(gòu)是這樣的

vue中如何實現(xiàn)一個換膚功能 

子組件

<setColor> 是 home 頁面 的一個子組件,而在一開始我們已經(jīng)說了,我們想在我們在app.vue (home.vue和其他view的父組件) 里面定義一個color變量,派發(fā)到各個view組件里面去。 于是這其實就是個,從 setColor 觸發(fā) app.vue 的設(shè)置顏色事件, 子組件向父組件通信的問題。

我們可以很直接地用綁定事件配合 emit() 的做法,在 app.vue 定義一個 setglobalColor 方法, 并綁定到router-view(包含了home.vue),接著在home組件繼續(xù)定義一個 setglobalColor 方法, 實現(xiàn)的功能就是 emit('setglobalColor') 去觸發(fā)app.vue的方法, 并把 home.vue 的這個 setglobalColor 繼續(xù)綁定到組件, 組件里面點選顏色時候,直接emit這個方法就行了。

為什么我想用事件巴士.vue 的事件巴士和 vuex, 在一些有追求的程序員手里總是小心翼翼的,我也一樣,因為作為涉及全局的東西,一般覺得能不用就不用,代碼能精簡就精簡,我們經(jīng)常用一個詞,不提倡。

可是有朝一日我經(jīng)常在想,代碼的可讀性可維護(hù)性,和性能以及“風(fēng)險”相對比,到底哪個更重要。對于事件巴士和vuex 這類全局性質(zhì)的方案的主要擔(dān)憂大部分在于, 他們是全局的,可能因為一個事件名變量名一致就造成沖突,在小型項目還會造成冗余和額外開銷。 但事實上,事件和變量的命名我們都可以通過約定去規(guī)范,而在表現(xiàn)上,使用了事件巴士和vuex的項目,在性能上和直接 props 傳遞數(shù)據(jù),emit 回調(diào)事件的項目相比,其實并沒有太大區(qū)別,反而是無止境的 props 和 emit ,給人一種麻煩難以維護(hù)的感覺。 像上述的 setglobalColor , 僅僅是跨越了兩層組件, 過程就顯得繁瑣了。所以我建議在出現(xiàn)兩級以上組件層次,數(shù)據(jù)流稍微多的項目中都可以這么去做,定義一個全局的事件巴士

export default (Vue) => {
 let eventHub = new Vue()
 Vue.prototype.$bus = {
  $on (...arg) {
   eventHub.$on(...arg)
  },
  $off (...arg) {
   eventHub.$off(...arg)
  },
  $emit (...arg) {
   eventHub.$emit(...arg)
  }
 }
}

將事件巴士綁定到當(dāng)前vue對象,使用時候只需要:

this.$bus.$on('set-theme', (color) => {··· })
this.$bus.$emit('set-theme', '#000000')

在這個demo中,我在app.vue 綁定了

this.$bus.$on('set-theme', (color) => {
   this.loadingColor = color
   this.userinfo.color = color
  })

而在 setColor.vue 則在點擊顏色塊時候觸發(fā) this.$bus.$emit('set-theme', color), 則能實現(xiàn)我們設(shè)置全局顏色的效果。這樣的好處在于,對于跨了多個層次,或者兄弟組件的通信,我們不再需要太繁瑣的props,比如我在header.vue 也綁定了 this.$bus.$on('set-theme', (color) => { }) ,在 this.$bus.$emit 發(fā)生時候,header 的背景顏色就能直接改變,而不需要等待app.vue 將 全局的color值props傳遞到header.vue里面(僅做示例,這里 header.vue 只是 app.vue 的下一層級,通過props數(shù)據(jù)流會更清晰)

而對于其他路由頁面組件,和 app.vue 都是直接上下級關(guān)系,我們依然采用props保持一個清晰的數(shù)據(jù)流向下傳遞, demo 里我是將 color 存在userinfo(以后還有其他數(shù)據(jù)), userinfo傳到每個子路由, 最后,每個頁面在創(chuàng)建時候,通過拿到這個全局的顏色,再用dom去更改對應(yīng)的樣式就好啦,例如

mounted () {
  this.$nextTick(() => {
   // 綁定設(shè)置主題的事件,一旦觸發(fā)修改主題,則將當(dāng)前字體顏色改為對應(yīng)顏色
   this.$el.querySelector('.myTitle').style.color = this.userinfo.color
   this.$el.querySelector('.weui-btn_primary').style.backgroundColor = this.userinfo.color
   this.$el.querySelector('.add_icon').style.color = this.userinfo.color
  })
 }

以上就是關(guān)于“vue中如何實現(xiàn)一個換膚功能”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

vue
AI