最近在寫一個vue項目,無心間出現了這樣一個小問題。css
一個單頁面應用,有視圖a和a.css,視圖b和b.css。而後通過webpack打包的時候,a.css b.css都會一次性加載進來,這樣若是第一次只顯示視圖a,b.css中的樣式和a.css中有衝突的話,就會影響視圖a的顯示。html
其實這個問題很簡單嘛,就是給a.css和b.css各自一個命名空間就好啦,保證css中的class名稱不會重複。vue
emmmmm... 感受有點太粗暴?webpack
仍是想了解一下有什麼官方解決方案,而後就進行了以下探究。web
給 <style>
標籤加入 scope
屬性,這樣它的 CSS 只做用於當前組件中的元素。vue經過PostCss來實現這樣的功能。算法
其原理在於爲style scope中的class定義屬性選擇器,同時在使用該class的標籤中添加該屬性。所以,style scope中定義的class只能在當前組件中使用。 例如:性能
// 轉化前 <style scoped> .example { color: red; } </style> <template> <div class="example">hi</div> </template> // 轉化後 <style> .example[data-v-f3f3eg9] { color: red; } </style> <template> <div class="example" data-v-f3f3eg9>hi</div> </template>
仔細想一想,這種方法和以前咱們本身的簡單粗暴的方法好像並無什麼本質上的區別。插件
而且存在一些缺點:code
給 <style>
標籤加入 module
屬性。component
配置:想要使用css modules須要在webpack配置文件中配置:
options: { cssModules: { // 設置命名格式 localIdentName: '[name]---[local]---[hash:base64:5]', camelCase: true } }
此時在通過webpack編譯時,會將css module中的class按照預設的命名規則生成統一的名字,用於區分使用。 例如:
// components/Button.css .normal { /* normal 相關的全部樣式 */ } .disabled { /* disabled 相關的全部樣式 */ } /* components/Button.js */ import styles from './Button.css'; console.log(styles); buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>` // 轉化後生成的html爲 <button class="button---normal---abc53">Submit</button>
其中 button---normal---abc53 是 CSS Modules 按照 webpack中的 localIdentName 規則自動生成的 class 名。其中的 abc53 是按照給定算法生成的序列碼。這樣能夠保證css名稱的一致性。
其實這種方法本質上和上述方法一致,保證css中class的惟一性,所有打包到一個css文件中,在加載的時候一次性所有加載。
感受最完美的方法應該是webpack按需加載css
可是想要抽出vue中的css的話須要使用ExtractTextPlugin插件,此插件沒法實現css的按需加載