<input id="0qass"><u id="0qass"></u></input>
  • <input id="0qass"><u id="0qass"></u></input>
  • <menu id="0qass"><u id="0qass"></u></menu>

    ant-design實現主題暗黑主題 和 亮色主題的 切換(實現網站黑白皮膚)

    最近在使用vite+react + ant-design 來搭建個人站點,看到網上好多網站都實現了黑白皮膚的切換,并且ant-design幫我們實現了三套主題色,一個默認亮白色暗黑主題緊湊主題。于是我也想來弄一弄。最后還是實現了,打包后也是ok的。

    效果

    在這里插入圖片描述

    思路

    對于網站需要切換主題的話,一般有以下幾種辦法。

    • 使用css覆蓋的方式,由于css基于后面的css覆蓋前面的原理,所以這一點也是可以的。但是這一點對于使用less和scss的碼友來說,貌似不是一個很好的方法
    • 由于less里面帶有一個less.jscdn,可以用來解析是html種使用less文件,但是這個需要注意使用的順序,需要less的樣式文件在前面,less.js的引用在后面,這個對于使用構建工具的同志來說不太友好,打包后less文件都不見了,直接使用路徑肯定也是不行。
    • 社區成熟的兩個庫: antd-theme-webpack-pluginantd-theme-generator,對于我的項目來說貌似都不怎么合適,首先:antd-theme-webpack-plugin這個庫是基于webpack來的,我們都知道vite是在開發環境使用esbuild,生產環境使用的是roallup來進行打包。antd-theme-generator這個庫的話,把less提升到了運行階段,我們代碼一般會進行打包壓縮等,如果使用這個庫的話就意味著需要配置less相關的靜態資源不能被打包,不然會有問題。

    基于上面的思路我做了以下的方法來進行嘗試。

    我的代碼地址是(這個地址不會改動): https://github.com/cll123456/blog

    項目做了以下調整:

    將ant-design的兩個主題,默認主題和暗黑主題引入到我自己的less文件中。然后對此就可以后序實現改動主題色,例如:成功,失敗,警告等。如下:
    在這里插入圖片描述

    這個引入的順序需要注意,后引入的變量會覆蓋前面的。不會自定義的會不生效
    在這里插入圖片描述

    在我點擊switch框的時候觸發方法。做以下嘗試

    所有的嘗試都是基于下面的第二步,也就是方法,這里面需要做啥事情

    嘗試一

    改變方法的時候直接來動態引入less文件,這樣在引入暗黑主題是可以實現的,但是從暗黑主題卻切換不過來了。如下:

    const handleSkin = (checked: boolean) => {
        if (checked) {
          // 明亮主題
           import('./../assets/style/index.less')
        } else {
          // 暗色主題
          import('./../assets/style/index.dark.less')
        }
      }
    

    這個從白的可以切換到黑的原因是,黑色樣式覆蓋了前面白色的樣式,但是如果你再一次覆蓋卻不行,我估計是選擇器權重問題上,ant官方做了改動。如果需要從新切換回來也是有辦法的,在明亮主題中直接window.location.reload(),這樣是可以切換回來的,如下圖:在這里插入圖片描述
    這樣雖然實現了功能,體驗肯定是不好的,作為一名前端工程師,肯定是需要非常注重體驗的,不然職業生涯的路可能就不會很長。

    嘗試二

    • 由于嘗試一不行,然后我就往import動態引入這邊考慮了,我考慮的方向是既然可以動態import引入,那么我可以再一次改變的時候把前一次引入的給remove掉么?
    • 但是我找遍了所有的文件,import導入的是無法remove掉的,import導入是現代瀏覽器里面的esm的語法。
    • 然后就去網上找各種方法,在ant-design pro中發現實現了這個功能,并且是無刷新的,然后就去gitup上看人家的源碼。功夫不負有心人,然后發現人家是動態使用link引入css的方式來實現的,那么我也可以來通過link導入less文件來實現,并且使用less.js的cdn來進行解析。

    添加一個addSkin的方法,畢竟需要導入文件,然后來查找原來是否存在,然后進行刪除。

    // 調用方法
    const handleSkin = (checked: boolean) => {
        if (checked) {
          // 明亮主題
            addSkin("./../../src/assets/style/index.less")
        } else {
          // 暗色主題
         addSkin("./../../src/assets/style/index.dark.less")
        }
      }
    // 添加皮膚的方法
    function addSkin(path: string) {
      let head = document.getElementsByTagName("head")[0];
      const getLink = head.getElementsByTagName('link');
      // 查找link是否存在,存在的話需要刪除dom
      if (getLink.length > 0) {
        for (let i = 0, l = getLink.length; i < l; i++) {
          if (getLink[i].getAttribute('data-type') === 'theme') {
            getLink[i].remove();
          }
        }
      }
      // 查找script是否存在
      const getScript = head.getElementsByTagName('script');
      if (getScript.length > 0) {
        for (let i = 0, l = getScript.length; i < l; i++) {
          if (getScript[i].getAttribute('data-type') === 'theme') {
            getScript[i].remove();
          }
        }
      }
    
      // 最后加入對應的主題和加載less的js文件
      let link = document.createElement("link");
      link.dataset.type = "theme";
      link.href = path;
      link.rel = "stylesheet";
      link.type = "text/css";
      head.appendChild(link);
      // 這個less.js一定要放到后面才行
      let script = document.createElement('script');
      script.type = 'text/javascript';
      script.dataset.type = 'theme';
      script.src = 'https://cdn.bootcdn.net/ajax/libs/less.js/4.1.1/less.js'
      head.appendChild(script)
    }
    

    這種方法是動態改變link標簽的樣式來實現的,在生產環境是沒有任何問題,但是在開發環境就不行了,打包后路徑不存在??隙ㄊ遣恍械?#xff0c;接下來我就去找vite如何靜態資源復制到打包的文件,方法找到了。但是我的less里面引用了antd里面的less,里面的也不用打包? 我覺得不太好,因此再一次放棄。

    嘗試三

    既然直接使用less文件不行,那我可以使用css不,和ant-design pro里面一樣的,我也來引用css文件,接下來就往這個方向。
    我直接打印了,import dark from './xxxx'.less 發現既然是一個字符串。
    在這里插入圖片描述
    是編譯好的字符串,那我直接使用style標簽就好了。說干就往下干。

    import dark from './../assets/style/index.dark.less'
    import lighter from './../assets/style/index.less'
    
    // 調用方法
    const handleSkin = (checked: boolean) => {
        if (checked) {
          // 明亮主題
            addSkin(lighter)
        } else {
          // 暗色主題
         addSkin(dark)
        }
      }
    // 添加皮膚的方法
    function addSkin(content: string) {
      let head = document.getElementsByTagName("head")[0];
      const getStyle = head.getElementsByTagName('style');
      // 查找style是否存在,存在的話需要刪除dom
      if (getStyle.length > 0) {
        for (let i = 0, l = getStyle.length; i < l; i++) {
          if (getStyle[i].getAttribute('data-type') === 'theme') {
            getStyle[i].remove();
          }
        }
      }
      // 最后加入對應的主題和加載less的js文件
      let styleDom = document.createElement("style");
      styleDom.dataset.type = "theme";
      styleDom.innerHTML = content;
      head.appendChild(styleDom);
    }
    
    • 這里有一個細節就是,樣式導入必須在頂部導入,不然vite會檢測不到,不能使用動態導入,打包會經過treeshake去掉.
    • 其實這里還有一個問題,那就是css打包后會比較大,畢竟引入了兩份,這個問題就留給碼友了,自己去vite獲取其他的構建工具(webpack, gulp等)上找靜態資源太大怎么處理。
      在這里插入圖片描述

    總結

    在真實的調試中肯定是不止這三遍嘗試的,這里只記錄走向成功的關鍵三步。More interest, less interests (多一些興趣愛好的向往,少一些功名利祿的追求)

    <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-size: 24px;">2021年02月01日</span>,<span style="margin: 0px; padding: 0px; font-size: 24px;">新版升級</span>課程“<span style="margin: 0px; padding: 0px; font-size: 24px;">Ant Design Pro實戰入門教程</span>”已上傳發布,希望客官們能夠<span style="margin: 0px; padding: 0px; font-size: 24px;">喜歡<span style="margin: 0px; padding: 0px; font-size: 16px;">,也希望這套課程能夠幫您節省大量學習時間</span></span>。</p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;"> </p> <p style="font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; margin: 0px; padding: 0px; color: #313d54; font-size: 16px; background-color: #ffffff;">Ant Design Pro是一個企業級中后臺前端/設計解決方案,秉承了 Ant Design 設計價值觀,致力于在設計規范基礎組件基礎上,繼續向上構建,提煉出典型模板/業務組件/配套設計資源。隨著設計者不斷反饋,Ant Design Pro將逐步沉淀總結出更多設計模式相應代碼實現,進一步提升企業級中后臺產品設計研發過程中用戶設計者體驗??傊?,Ant Design Pro是一套基于 React 中后臺管理控制臺腳手架,可以幫助你快速搭建企業級中后臺產品原型。</p>
    相關推薦
    ??2020 CSDN 皮膚主題: 點我我會動 設計師:白松林 返回首頁
    多乐彩