爲什麼要使用scoped
vue中爲了讓樣式私有化,不至於當前組件的css樣式對全局造成污染,添加了scoped屬性,但同時也要慎重的使用,因爲一旦出現問題,排查起來可能會很麻煩。
scoped工作原理
我們平時開發vue的時候可能會比較好奇,經常會看到data-v-asf23235kd33k
在dom元素中出現,其實這就是scoped做的事情,比如我們一個button
組件,我們定義瞭如下scoped樣式,給按鈕添加一個邊框弧度。
<template>
<button class="button">text</button>
</template>
<style scoped>
.button {
border-raduis: 1px;
}
</style>
這樣最終渲染出來的頁面代碼應該是這樣的
<button class="button" data-v-123lsdfasi32>
text
</button>
.button[data-v-123lsdfasi32]{
border-raduis: 1px;
}
可以看到這樣一來,本頁面定義爲scoped下的樣式屬性,僅可能作用於當前組件,即使該組件被引用,也不會和其他的button屬性產生衝突。
總結:
- 給DOM節點添加一個標誌屬性
- 給滲透DOM節點的樣式屬性添加一個屬性選擇器。(間接提升了樣式的權重)
對上述情況做一下補充說明,css屬性會疊加,類屬性和屬性選擇權重爲 0 0 1 0,疊加後權重變爲0 0 2 0,所以通過一個簡單的類屬性可能無法覆蓋了,需要一個id選擇器或者內聯樣式。
實際使用
在引用組件到頁面中的時候,總是會有需求說本頁面修改一下組件的樣式吧,但是由於scoped屬性產生的data-v-12jfsjjj
只會作用於組件DOM元素的最外層標籤,所以父組件的樣式不會滲透到子組件中去【這裏要自行理解一下爲什麼無法滲透,不做舉例】。如果不使用scoped又怕樣式滲透到全局?可以使用滲透scoped穿透
,個人理解這樣的工作原理爲沿用子組件生成的序列號,不重新生成。
.outer /deep/ .button { // outer爲組件外層屬性樣式名稱,沒有的話也可以不加
border-raduis: 1px;
}
注意,如果使用stylus,滲透符號爲 >>>
。
動態生成的DOM類名可能在scoped中也不會有作用,這個時候也可以添加/deep/來讓樣式生效。
問題回顧
在之前的項目中,有一次樣式污染導致了一個比較嚴重的後果,我的自定義的一個摺疊框,當項目一開始運行的時候不會出問題,但是項目運行一段時間之後,摺疊框的內容就都看不到了,DOM節點都是有的,樣式卻變成了
opacity: 0;
這個問題當時我通過行內樣式設置爲!important
解決掉了,由於開發的是移動端,結果發現這個問題耗費了很長的時間,當時沒有細究,今天學習後發現有一個組件使用過程中定義了一個和我一樣的class屬性,但是他卻沒有把這個屬性放到<scoped>
中(當然了,作爲一個公共組件組件這樣使用肯定是不合理的),直接導致了他的樣式合併到了同名的我的樣式中,導致了這個問題,希望大家引以爲戒。