webpack less 抽取小技巧 - css多主題使用篇

上一篇 webpack less 抽取小技巧 中說到,可以進行多主題的引入。此篇咱們就來實現一下如何引入多個css主題;

基本環境介紹

前置:

  • 已經存在多套css主題放置在服務端
  • 使用切換按鈕 (或者其他交互切換)

css 主題切換思路講解
*方案一 link 引入,每次切換的時候,更換href,動態引入css;(用瀏覽器本身的 304 獲取緩存,但是這種容易被瀏覽器限制)

*方案二 ajax獲取資源,配合style寫入樣式,切換的時候,多次獲取資源 (由于多次獲取資源,可以在本地緩存已經請求的資源,同一份資源不做二次請求)(由于ajax請求,所以受瀏覽器請求的限制,比如請求并發限制(如下圖),所造成瀏覽器響應時間過高)

瀏覽器并發.png
  • 終極方案 根據方案二出現的問題,將方案一二進行整理;實現思路如下:首頁添加默認的link css鏈接,在進行主題切換的之后,繼續執行緩存策略,并將link刪除;好處:這種能避免在第一次ajax請求之前導致的樣式錯亂問題;缺陷:需要進行ajax 請求的資源才能獲取

代碼呈現:
功能代碼:

// base vue , 但是功能本身不依賴框架,反倒是對瀏覽器dom有依賴
// template
<!-- 切換皮膚一 -->
<li @click="_changeThemeFun('1')">
    <sf-svg-icon iconClass="state-portal"></sf-svg-icon>
    <span>換膚一</span>
</li>
<!-- 切換皮膚一 -->
<li @click="_changeThemeFun('2')">
    <sf-svg-icon iconClass="state-portal"></sf-svg-icon>
    <span>換膚二</span>
</li>
//.....
// 換膚
async _changeThemeFun(type) {
    // 擴展的theme映射
    // const transTheme = {
    //     ['0']: '0',
    //     ['1']: '1',
    //     ['2']: '2',
    // };
    // 不存在則渲染 + 加載
    // 存在則清除后渲染 + 加載
    const theme = document.querySelector('#theme-link');
    console.log('theme', theme);
    // css link
    // this.loadCSS(`/theme/theme${type}.css`);
    // style
    // axios.get(`/theme/theme${type}.css`).then(res => {
    //     const cssText = res.data || '';
    //     this.loadStyle(cssText);
    // })
    // 請求優化
    const cssText = await this.getCssTextFun(type);
    this.loadStyle(cssText);
    // 存在,則清除
    if (theme) {
        // theme.remove();
        let themeParent = theme.parentElement;
        themeParent.removeChild(theme);
    }
},
async getCssTextFun(type) {
    if (!this.theme[type]) {
        return axios.get(`/theme/theme${type}.css`).then(res => {
            const cssText = res.data || '';
            this.theme[type] = cssText;
            return Promise.resolve(this.theme[type]);
        });
    } else {
        return Promise.resolve(this.theme[type]);
    }
},
loadStyle(cssText) {
    const STYLE_ID = 'style-css';
    const target = document.getElementById(STYLE_ID);
    const setCssTxt = (style, cssText) => {
        try {
            // firefox、safari、chrome和Opera
            // style.clear();
            console.log('style', style);
            // style.innerText = '';
            // style.appendChild(document.createTextNode(cssText));
            style.innerText = cssText;
        } catch (ex) {
            // IE早期的瀏覽器 ,需要使用style元素的stylesheet屬性的cssText屬性
            style.styleSheet.cssText = cssText;
        }
    };
    if (target) {
        setCssTxt(target, cssText);
        return;
    }
    const style = document.createElement('style');
    style.setAttribute('id', STYLE_ID);
    setCssTxt(style, cssText);
    document.head.appendChild(style);
},
loadCSS(url) {
    const LINK_ID = 'url-link';
    // 存在
    const target = document.getElementById(LINK_ID);
    if (target) {
        target.setAttribute('href', url);
        return;
    }
    // 不存在
    const element = document.createElement('link');
    element.setAttribute('rel', 'stylesheet');
    element.setAttribute('type', 'text/css');
    element.setAttribute('id', LINK_ID);
    element.setAttribute('href', url);
    document.head.appendChild(element);
},

配合的頁面:

// index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <title></title>
        <link rel="stylesheet" href="<%= BASE_URL %>css/element/index.css">
        <!-- css 引入 -->
        <link rel="stylesheet" id="theme-link" type="text/css" href="<%= BASE_URL %>theme/theme.css">
    </head>
</html>

以上,有問題請留言討論,謝謝大家~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容