剛開始使用vue的時候容易被里面的樣式搞懵:
樣式可以在main.js中引入,在模塊js文件中引入,在組件中的style標簽引入,在組件中的script標簽引入,還可以在index.html的body中引入。
我不禁要問:
1、從不同位置引入的樣式到底是什么關系?
2、在實際定義樣式時應該定義在哪個位置,以避免樣式產生的沖突?
紙上得來終覺淺,絕知此事要躬行。看十次文檔,不如做一個測試。
新建一個最簡單的項目並運行:如果你人品沒問題,會看到彈出的瀏覽器中,head標簽內有這樣的style
在項目src目錄中找找看:
第一個style在\src\App.vue文件的style中
第二個style在\src\components\HelloWorld.vue文件中
App.vue是所有路由的出口,包含HelloWorld.vue,因此頁面先加載App.vue的style,再加載HelloWorld.vue的style。看起來很簡單,先加載的會先出現,根據頁面樣式的規則,如果有相同的類定義,后者會覆蓋前者。
但是我想就開頭出現的問題了解得更深入。為避免多個問題糾纏在一起,我逐個去分析:
加載順序的問題
1、為方便看到測試的結果,我改造一下項目:


原來main.js里先引入了App.vue文件,所以它先執行App.vue里的script,從而引入了app.css
隨后引入router,router里引入了HelloWorld.vue,繼而加載hello.css
加載完App.vue后才按順序加載main.css,於是有了上面的結果。
而所有組件的style都是script里的代碼執行完后再加載。
所以我大致可以得出結論:
樣式從main.js入口開始順序加載,
遇到組件則加載組件中script所引入的樣式,
先處理完所有scipt中的引入,
再處理style,
style按包含關系從外到內加載
但是問題還沒完,我又得出另外的問題:這些頁面都是固定的,如果是異步加載頁面,當路由切換到另一個頁面時,此頁面原來的樣式是否會刪除,當前頁面的樣式會添加到哪里?
2、為此我又再路由中添加了ComB.vue,並且使用異步加載該組件。
再看瀏覽器:先只會加載到app-style
點擊hello之后,加載hello-style
點擊comb之后,異步加載comb組件,先引入comb-import,再引入comb-style
可以看到,瀏覽器先加載1.js組件文件,然后執行script加載comb.css,再加載ComB.vue的style,而當我切換回ComA頁面時,head標簽內的樣式不再有變化。
另外可以看到,當我更改路由使HelloWorld不在根路徑顯示,HelloWorld就只加載hello.css,而不會加載HelloWorld的style,只有HelloWorld頁面顯示出來時才加載。
3、我再看看如果把helloworld也改成異步組件會怎么樣?
可以看到之前第二個加載的hello-import沒有了,然后先點擊誰,誰就先加載
所以可以知道:如果ComA和ComB都是異步組件,則先打開哪一頁就加載哪一頁的script和style
再定義一個ComBB,在ComB中引入,但不顯示,則ComBB只顯示comb_b.css,但不顯示style
所以:加載順序應再加兩條規則:
異步組件先顯示的先加載
沒有顯示的頁面或者組件不加載style
4、再看一個問題:一個組件內可以定義不止一個style,並且有scoped的style和沒有scoped的style可以並存,它們會按照所定義的順序加載。
看瀏覽器,按順序加載:
<style type="text/css"> .noScope1.noScope2{ height: 50px } </style>
<style scoped> .comb-style{ color: red; } </style>
<style type="text/css"> .noScope2{ border: 1px solid red; height:20px; } </style>
並且我把樣式稍微做了改變,比如先給noScope2加height,發現覆蓋了noScope1的高度;再然后,給.noScope1加上.noScope2,高度又變成50,
也就是說:跟普通CSS擁有一樣的權重優先機制。
5、再看寫在body內的樣式
通過main.js控制的樣式都在head標簽中顯示,由此就可以知道,如果我在body內定義樣式,是可以把head標簽內的同名樣式覆蓋掉的。
但要注意的是,在body內引入的樣式,因為已經不在main.js控制范圍內,也就是不參與打包,所以必須定義在static靜態資源目錄內。
同時要注意,在body引入的樣式不在src文件夾內,沒有熱更新的功能,所以每次更改后需要手動刷新頁面。
6、總結
經過以上的測試,可以得知style出現的順序跟你定義的位置,是否異步組件,初始狀態是否顯示有關。而樣式的覆蓋又可以通過添加scoped和在body內添加樣式文件來控制。相信單頁應用要精准控制樣式絕對不是難事。