深入理解vue中的scoped屬性
1,前言
我們知道vue為了防止css樣式污染,在每個組件中提供了
scoped屬性進行限定css作用域;
當<style>標簽有 scoped 屬性時,它的 CSS 只作用于當前組件中的元素。
2,scoped原理
1, vue中的
scoped屬性,其實就是給每一個dom節(jié)點元素都添加了不重復(fù)的自定義屬性(如:data-v-6810cbe5);
2,然后編譯時再給樣式的末尾添加屬性選擇器進行樣式私有化(如.btn[data-v-6810cbe5]);
如下:
轉(zhuǎn)譯前的代碼:
btn組件(使用了Vant組件庫的button組件):
<template>
<div class="copy1">
<van-button type="default">默認按鈕</van-button>
</div>
</template>
<style scoped lang="scss">
.van-button {
background-color: red;
}
</style>瀏覽器編輯的結(jié)果如下:

可以看到,van-button類名后面添加了[data-v-03f66e5f];他的節(jié)點上面也自動添加了自定義屬性 data-v-03f66e5f;
所以:就算在兩個互不相關(guān)的組件使用同樣的類名,他們的樣式也是互不影響的;
3,父子組件使用scoped的不同情況
scoped的這一操作,雖然達到了組件樣式模塊化的目的,但是會出現(xiàn)無論父組件樣式的權(quán)重有多大,也可能無法修改子組件的樣式;
下面就分四種情況具體說明scoped的作用:
4,第一種:父組件未添加scoped,子組件未添加scoped

這是最原始的一種情況,可以看到按鈕的背景顏色為藍色。此時父組件聲明了background-color: blue;,子組件聲明了background-color: red,權(quán)重是一樣的,但是父組件style會覆蓋子組件的style;
查看Elements后會發(fā)現(xiàn),父組件的樣式文件插入位置在子組件樣式文件后面(上圖可以看出一個是第9行一個是第90行),對于權(quán)重相同的樣式,后面的會覆蓋前面,所以父組件的style生效。
5,第二種:父組件未添加scoped,子組件添加scoped
子組件:btn.vue
<template>
<div class="copy1">
<van-button type="default">默認按鈕</van-button>
</div>
</template>
<style lang="scss" scoped>
.van-button {
background-color: red;
}
</style>
我們可以看到子組件的.van-button{background-color: red};被編譯成.van-button[data-v-03f66e5f]{background-color: red};
子組件中button樣式的權(quán)重=類選擇器(.button)+屬性選擇器([data-v-03f66e5f]),而父組件中button樣式的權(quán)重=類選擇器(.button),所以子組件樣式的權(quán)重加重了,覆蓋本來能產(chǎn)生作用的父組件樣式,導(dǎo)致按鈕背景顏色為紅色。
6,第三種:父組件添加scoped,子組件未添加scoped
父組件:
<template>
<div>
<!-- 使用子組件 -->
<div class="scoped1">
<btn></btn>
</div>
</div>
</template>
<script>
//引入
import Btn from './copy1/index.vue';
export default {
name: 'copy',
components: {
Btn,
},
};
</script>
<style lang="scss" scoped>
.scoped1 {
.van-button {
background-color: blue;
}
}
<style>子組件:btn.vue
<template>
<div class="copy1">
<van-button type="default">默認按鈕</van-button>
</div>
</template>
<style lang="scss">
.van-button {
background-color: red;
}
</style>
我們可以看到按鈕的背景顏色為紅色,父組件style添加scoped后,所有元素都加上data-v屬性,包括子組件的根節(jié)點,但是子組件的內(nèi)層元素就不會受影響,所以父組件的.van-button[data-v-ae1b895c] {background-color:blue;}作用不到子組件的.van-button上。
這也是直接修改element-ui或vant-ui子組件的樣式不生效的原因,就算要寫,也需要借助深度作用選擇器或樣式不寫在scoped屬性中。
注意:
如果只修改子組件根節(jié)點的樣式,還是可以寫到父組件的scoped CSS里面,因為一個子組件的根節(jié)點會同時存在 兩個data-v屬性的,一個是父組件本來的,另一個是子組件根節(jié)點上面的;(見上圖左邊部分);所以也會影響到子組件的根節(jié)點元素;
7,第四種:父組件添加scoped,子組件也添加scoped
效果圖如下:

我們可以看到,子組件的根節(jié)點不僅有子組件的data-v屬性,還有父組件的data-v屬性。而.van-button元素依然不受父組件的影響,只擁有自己組件的data-v屬性,所以按鈕顏色依舊為紅色。
這和上面第三種的情況是一樣的;如法直接覆蓋子組件的樣式;
8,解決方案
那如果我就是想讓父組件的樣式覆蓋子組件的樣式,怎么辦呢?
1,第一種使用兩個style,一個用于私有樣式(加scoped),一個用于共有樣式。
<style lang="scss" scoped>
.van-button {
....
}
// 公共樣式
<style lang="scss" >
.van-button {
background-color: blue;
}2,深度作用選擇器
父元素使用 /deep/ 或 >>>進行穿透
<style lang="scss" scoped>
/deep/ .scoped1 {
.van-button {
background-color: blue;
}
編譯如下:
[data-v-ae1b895c] .scoped1 .van-button {
background-color: blue;
}
}
<style>有些像 Sass 之類的預(yù)處理器無法正確解析 >>>。這種情況下你可以使用 /deep/ 或 ::v-deep 操作符取而代之——兩者都是 >>> 的別名,同樣可以正常工作。
推薦使用 /deep/ 簡單方便;
9,總結(jié)
1,scoped CSS里每個樣式的權(quán)重加重了,理論上我們可以修改某一個樣式,但是卻需要更高的權(quán)重去覆蓋這個樣式;
2,無論父組件樣式的權(quán)重多大,也可能無法修改子組件的樣式,除了子組件的根節(jié)點。
到此這篇關(guān)于vue中的scoped屬性的文章就介紹到這了,更多相關(guān)vue scoped屬性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue實現(xiàn)獲取后端接口API代碼片段(已封裝Service方法名)
Vue實現(xiàn)獲取后端接口API代碼片段(已封裝Service方法名),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
vue router總結(jié) $router和$route及router與 router與route區(qū)別
這篇文章主要介紹了vue router總結(jié) $router和$route及router與 router與route區(qū)別,本文給大家介紹的非常詳細,具有一定的參考借鑒價值 ,需要的朋友可以參考下2019-07-07
element?el-upload文件上傳覆蓋第一個文件的實現(xiàn)
這篇文章主要介紹了element?el-upload文件上傳覆蓋第一個文件的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03

