- 設計思路
- 主題建立
- 配置webpack
- 配置供js使用的主題檔案路徑
- 使用及調試
- 優勢及問題
- 源碼
- 本系列目錄
最近因為某些原因,終于把一直糾結的主題方式及切換方式搞了出來。
設計思路
我能想到的主題切換方式無非兩種:
- 一種是在body中加樣式,對所有css進行命名空間(css字首)處理
- 一種是類似Element自身的主題切換方式,通過編寫scss改變主題
前一種方式在花褲衩同學的vue-element-admin中有具體的實作,項目首頁:https://github.com/PanJiaChen/vue-element-admin
他是先将element自己提供的變量檔案修改後生成新的css,然後将該css用gulp進行二次編輯增加命名空間,然後引入。也就是說他隻是修改了UI架構的主題,并沒有修改自己寫的樣式主題。
第二種方式則是element自己生成一個sass變量檔案,執行指令行後生成新主題,然後讓開發者自己導入。
以上兩種其實都并沒有實作項目本身自定義樣式的主題切換,是以就産生了很多的問題。但仔細分析一下,其實我們隻要将自己寫的css樣式也如同element官方那樣打包一遍,然後動态引入就好了嘛。當然也可能是我傻,沒想到還有其他方法。
介于以上總結,項目中設計的主題加載和切換方式大緻流程如下:
1. 頁面中僅引入基本樣式
2. 頁面初始化完成,動态加載主題檔案
3. 使用者切換主題:判斷主題檔案是否已經存在,存在則不操作;不存在則清空所有的主題檔案,然後動态加載對應的主題檔案。
主題建立
目前主題編寫參考了Element的主題切換方式,通過sass進行變量修改。
# 複制基礎變量檔案 (src/assets/css/theme/default.scss),重命名為 blue.scss 并修改内部變量
# 在 src/assets/css 目錄中建立新的主題入口檔案 theme-blue.scss,并做如下引入
// 引入新主題變量檔案
@import './theme/blue'
// 引入預設主題
@import './theme-default'
如此簡單的便可以完成主題建立。前文說過我們需要動态引入檔案,而動态引入我采用的是js讀取檔案路徑并加載的形式,也就意味着該檔案必須存在實際的實體位址,是以你需要先對項目進行打包,生成對應的靜态的css檔案,而不是scss檔案。為了達成這個目的我們還需要對webpack進行設定。沿着這個思路我們還需要做以下工作。
配置webpack
在webpack.prod.conf.js中對入口變量做出修改,注意是prod.js
// 增加新的入口,并賦予檔案名和路徑
entry: {
'theme-default': './src/assets/style/theme-default.scss'
}
// 對HtmlWebpackPlugin插件增加忽略chunk設定,防止該chunk被加入到生成後的html中
new HtmlWebpackPlugin({
excludeChunks: ['theme-default']
})
配置供js使用的主題檔案路徑
配置好新的入口後,我們對項目進行打包,等待編譯完成。當打包結束後我們應該能夠看到在
dist\static\css
下有新增的theme檔案,這個檔案就是我們的主題檔案了。接下來則是為主題切換做基礎。我們需要把生成的檔案路徑提供給js。但是要意識到,該檔案在開發時是沒有的,隻有在打包完成後才有,是以我們需要另一個操作:改寫打封包件。
在打封包件生成後,我們需要利用node循環讀取
dist\static\css
下的所有檔案,并把所有的theme檔案路徑輸出到html中,當然你也可以輸出到公共js中,比如app.js。這裡具體的實作方法請看
build\themeExtract.js
寫完檔案後我們隻需要執行它就可以了。當然了,把它直接和
npm run build
綁定到一起不是更好嗎?是以在
package.json
中做如下修改即可
"scripts": {
"dev": "node build/dev-server.js",
"start": "node build/dev-server.js",
// &&代表順序執行
"build": "node build/build.js && node build/themeExtract.js"
}
執行後,我們再看看打包後的html檔案,在head部分能看到一個全局的變量themeURL,裡面就是我們需要的所有的主題檔案路徑了。
使用及調試
在上個步驟中我們已經有了全局變量themeURL,那麼隻需要對主題檔案進行比對即可。當更換主題時,我們先查找已經加載的主題,如果沒有則直接插入主題檔案,如果有則清空所有主題檔案,然後再插入。至于動态插入檔案的方法,項目中已對該方法進行封裝,可在
src\util\changeTheme.js
中檢視。
# 使用主題切換的方法示例,需要保證changeTheme()中的參數與主題檔案名保持一緻
@import changeTheme from '@/util/changeTheme'
export default {
loadTheme(theme){
changeTheme(theme)
}
}
因為主題檔案是打包後才生成的,是以在開發環境中,主題切換并不好用,隻能通過手動修改sass主題檔案的方式來做切換了,這也是目前該方案最大的問題。
至于調試動态載入主題js是否成功…..唔,你先打包一份,然後把打包後的多出來的變量複制到 src\index.html 中,再把打包出來的檔案放到和src同級的static目錄中就可以了嘛…
優勢及問題
這種切換方式能夠最大程度上避免CSS污染,頁面也更加幹淨,不會産生多餘的檔案。
如果使用偷懶的方法,将所有自己寫的樣式都放到主題中(比如我),那麼後期維護也異常的簡單,改改變量值就可以了嘛。
如果使用繁瑣的方法,抽出所有樣式中的主題部分(如背景色、文字、顔色、圖檔等),也能極大減少主題檔案的大小,就是後期維護的時候會同時看兩個檔案才能知道這裡真正的樣式是什麼,而且在編輯時容易丢東西。
源碼
目前源碼位址:https://github.com/harsima/vue-backend
請注意,該源碼會不斷更新(因為工作很忙不能保證定期更新)。源碼涉及到的東西有超出本篇教程的部分,請酌情閱讀。
本系列目錄
- Vue + ElementUI 手撸背景管理網站基本架構(零)前言篇
- Vue + ElementUI 手撸背景管理網站基本架構(一)建立項目
- Vue + ElementUI 手撸背景管理網站基本架構(二)權限控制
- Vue + ElementUI 手撸背景管理網站基本架構(三)登入及系統菜單加載
- Vue + ElementUI 手撸背景管理網站基本架構(四)主題切換