web自定義主題實現方案

需求背景

A用戶:我喜歡亮色!B用戶:我喜歡暗色系!...在實際的開發場景中,主題需求通常都是必不可少的,那咱們如何簡單地實現咱們想要的效果呢!css

解決方案

話很少說,咱們先看一下demo效果html

實現思路:在頁面的載體上自定義一個屬性標籤,用於記錄切換不一樣的主題,而後咱們的css文件會根據屬性標籤值的改變而加載不一樣樣式,來實現咱們切換主題的效果。乾巴巴的描述,理解起來有點晦澀難懂,這裏我以本身寫的demo爲例,和你們一塊兒交流探討。前端

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style type="text/css">
</head>

<body customize-theme-style="dark">
  <app-root></app-root>
>
</body>

</html>
複製代碼

目前不少單頁面應用都會有一個index.html載體文件,路由<app-root></app-root>掛載在body節點上,因此咱們的頁面組件都是掛載在body上,那麼咱們在body節點上定義一個customize-theme-style="dark"屬性標籤用於記錄主題狀態的切換。接下來就是css會根據主題狀態的切換來改變主題樣式。 我這裏CSS 預處理語言用的是less(若是你用的是sass,或者是其餘的css預處理語言,思路都是相同的,語法上有些許不一樣而已),在資源文件夾裏建一個styles用於存放咱們的less樣式文件,demo的編譯環境是angular8.0,因此咱們要在angular.json腳手架文件聲明咱們新建的資源文件(這裏我就不詳細說明配置過程了,不一樣的前端框架,配置過程不一樣,但框架歷來不是技術實現的障礙,思路是同樣的), json

如上圖所示index.less用來定義主題樣式以及覆蓋第三方組件樣式,theme.less用於定義全局的樣式變量 在index.less中:

// 暗黑主題
[customize-theme-style='dark'] {
  //背景
  .alain-default {
    background: @background-color;
  }

  //表格
  .ant-table-thead>tr>th {
    background-color: @table-head-color;
    color: @font-color;
  }

  ......
}
// 亮色主題
[customize-theme-style='light'] {
  ......  
}
......
複製代碼

主題狀態的改變會加載不一樣的css樣式,接下來就是如何改變主題樣式狀態了sass

實現思路:咱們將用戶設置的主題狀態用localStorage存儲在本地,若是用戶沒有設置,就加載默認主題。bash

//獲取用戶上次設置的主題
    this.themeSkin = this.storageService.getStorageValue('customize-theme');
    if (this.themeSkin) {
      //設置主題
      const body = document.getElementsByTagName('body')[0];
      body.setAttribute('customize-theme-style', this.themeSkin);
    }
    //切換主題
    changeSkin(skin) {
    const body = document.getElementsByTagName('body')[0];
    body.setAttribute('customize-theme-style', skin);
    //存儲主題
    this.storageService.setStorageValue('customize-theme', skin);
  }
複製代碼

完成以上步驟就基本上實現了自定義主題的切換需求。前端框架

然而事情並無這麼簡單!!!app

如今的框架都是提倡頁面組件化,那麼咱們本身寫的組件怎麼適配主題呢? 所謂的適配也就是讓組件讀取當前載體文件body節點(根節點)上的主題屬性值,這個也不難作到。 舉個栗子:框架

//自定義組件中的樣式
:host-context([customize-theme-style='dark']) h4 {
   .mixin-font-color('dark');
 }
 
:host-context([customize-theme-style='light']) h4 {
   .mixin-font-color('light');
}

//index.less

.mixin-font-color(@a) when(@a='dark') {
  color: #ffffff;
}

.mixin-font-color(@a) when(@a='light') {
  color: #212121;
}

複製代碼

編譯後的css樣式: [customize-theme-style='dark'][_nghost-fkw-c5] h4[_ngcontent-fkw-c5], [customize-theme-style='dark'] [_nghost-fkw-c5] h4[_ngcontent-fkw-c5] { color: #ffffff; }less

:host-context()僞類選擇器能夠讀取最外層的掛載點上的屬性,經過這一特性就能實現組件主題化了 (API:angular.io/guide/compo…) 這裏就給咱們的組件中標題生成了一個惟一的樣式。 至此,咱們的主題需求問題就迎刃而解了。 若是有什麼疑問或者你有更好的解決方案,歡迎留言交流,謝謝~

相關文章
相關標籤/搜索