得益於 Vue-loader,在 Vue 中能夠使用相似於 Web Component 的組件化寫法,<template></template><style></style><script></script>
,在大多數狀況下,咱們但願組件間定義的樣式是相互隔離的,在 Weex 當中的確如此,組件天生隔離,但是在 Vue 當中,運行的載體仍是瀏覽器,全部的樣式類仍是會經過 style 標籤插入頭部,影響全局,交叉污染css
依然是 Vue-loader,經過爲組件中的 style 標籤增長一個 scoped 標識,Vue-loader 在編譯的過程當中會爲組件每個元素節點增長 scopeId 做爲屬性,同時爲全部的樣式類加上屬性選擇器 scopeId,從而達到隔離的效果,大概是下面的樣子:html
每一個組件有惟一的 scopeId,按理說,這樣應該可以作到樣式隔離了,實際上,這種方式其實表現已經足夠好了,除了如下這種狀況~~前端
咱們把上面的例子再完善下:vue
// 父組件
<template>
<div>
<div class="bg"></div>
<Sub></Sub>
</div>
</template>
<script>
import Sub from './sub';
export default {
components: { Sub }
};
</script>
<style scoped>
.bg {
background-color: #000;
width: 100px;
height: 100px;
}
</style>
// 子組件
<template>
<div class="bg">
</div>
</template>
<script>
export default {
};
</script>
<style scoped>
.bg {
width: 300px;
height: 300px;
margin-top: 5px;
}
</style>複製代碼
因爲咱們使用了 scoped 標識進行樣式隔離,子組件的 div 不該該有任何背景顏色,但是現實總在狠狠的打臉~~瀏覽器
不知道你的媚眼看到問題的所在了沒:
子元素的根元素會繼承父元素的 ScopeId!
子元素的根元素會繼承父元素的 ScopeId!
子元素的根元素會繼承父元素的 ScopeId!(說了三遍的話,確定很重要)
因爲子元素的根元素除了擁有本身的 ScopeId 屬性,還繼承了父元素的 ScopeId 屬性,因此父元素的樣式類 bg 對其依然有效bash
破解的方式也很簡單,爲每個組件的根元素提供一個另類一點的樣式名(若是有的話),例如就不要每一個組件都命名爲:wrap,根據業務名爲:b1-wrap、b2-wrap 等組件化
組件中的非根元素,類名無論怎麼命名,怎麼重名,都是不會發生污染的,這個本身領悟~~ui
感謝 @WayneZheng、@花褲衩的提醒
也許有同窗跟我同樣不夠細心,沒有注意,此文的意義用於提醒了code
此文還在公衆號菲麥前端中發佈: