深入理解vue中的scoped屬性
1,前言
我們知道vue為了防止css樣式污染,在每個(gè)組件中提供了
scoped
屬性進(jìn)行限定css作用域;
當(dāng)<style>
標(biāo)簽有 scoped 屬性時(shí),它的 CSS 只作用于當(dāng)前組件中的元素。
2,scoped原理
1, vue中的
scoped
屬性,其實(shí)就是給每一個(gè)dom節(jié)點(diǎn)元素都添加了不重復(fù)的自定義屬性(如:data-v-6810cbe5);
2,然后編譯時(shí)再給樣式的末尾添加屬性選擇器
進(jìn)行樣式私有化(如.btn[data-v-6810cbe5]);
如下:
轉(zhuǎn)譯前的代碼:
btn組件(使用了Vant組件庫的button組件):
<template> <div class="copy1"> <van-button type="default">默認(rèn)按鈕</van-button> </div> </template> <style scoped lang="scss"> .van-button { background-color: red; } </style>
瀏覽器編輯的結(jié)果如下:
可以看到,van-button類名后面添加了[data-v-03f66e5f]
;他的節(jié)點(diǎn)上面也自動(dòng)添加了自定義屬性 data-v-03f66e5f
;
所以:就算在兩個(gè)互不相關(guān)的組件使用同樣的類名,他們的樣式也是互不影響的;
3,父子組件使用scoped的不同情況
scoped的
這一操作,雖然達(dá)到了組件樣式模塊化的目的,但是會(huì)出現(xiàn)無論父組件樣式的權(quán)重有多大,也可能無法修改子組件的樣式;
下面就分四種情況具體說明scoped的作用:
4,第一種:父組件未添加scoped,子組件未添加scoped
這是最原始的一種情況,可以看到按鈕的背景顏色為藍(lán)色。此時(shí)父組件聲明了background-color: blue;
,子組件聲明了background-color: red
,權(quán)重是一樣的,但是父組件style會(huì)覆蓋子組件的style;
查看Elements后會(huì)發(fā)現(xiàn),父組件的樣式文件插入位置在子組件樣式文件后面(上圖可以看出一個(gè)是第9行一個(gè)是第90行),對于權(quán)重相同的樣式,后面的會(huì)覆蓋前面,所以父組件的style生效。
5,第二種:父組件未添加scoped,子組件添加scoped
子組件:btn.vue
<template> <div class="copy1"> <van-button type="default">默認(rèn)按鈕</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">默認(rèn)按鈕</van-button> </div> </template> <style lang="scss"> .van-button { background-color: red; } </style>
我們可以看到按鈕的背景顏色為紅色,父組件style添加scoped后,所有元素都加上data-v屬性,包括子組件的根節(jié)點(diǎn),但是子組件的內(nèi)層元素就不會(huì)受影響
,所以父組件的.van-button[data-v-ae1b895c] {background-color:blue;}
作用不到子組件的.van-button上。
這也是直接修改element-ui或vant-ui子組件的樣式不生效的原因,就算要寫,也需要借助深度作用選擇器或樣式不寫在scoped屬性中。
注意
:
如果只修改子組件根節(jié)點(diǎn)的樣式,還是可以寫到父組件的scoped CSS里面,因?yàn)橐粋€(gè)子組件的根節(jié)點(diǎn)會(huì)同時(shí)存在 兩個(gè)data-v屬性的,一個(gè)是父組件本來的,另一個(gè)是子組件根節(jié)點(diǎn)上面的;(見上圖左邊部分);所以也會(huì)影響到子組件的根節(jié)點(diǎn)元素;
7,第四種:父組件添加scoped,子組件也添加scoped
效果圖如下:
我們可以看到,子組件的根節(jié)點(diǎn)不僅有子組件的data-v屬性,還有父組件的data-v屬性。而.van-button元素依然不受父組件的影響,只擁有自己組件的data-v屬性,所以按鈕顏色依舊為紅色。
這和上面第三種的情況是一樣的;如法直接覆蓋子組件的樣式;
8,解決方案
那如果我就是想讓父組件的樣式覆蓋子組件的樣式,怎么辦呢?
1,第一種使用兩個(gè)style,一個(gè)用于私有樣式(加scoped),一個(gè)用于共有樣式。
<style lang="scss" scoped> .van-button { .... } // 公共樣式 <style lang="scss" > .van-button { background-color: blue; }
2,深度作用選擇器
父元素使用 /deep/ 或 >>>進(jìn)行穿透
<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里每個(gè)樣式的權(quán)重加重了,理論上我們可以修改某一個(gè)樣式,但是卻需要更高的權(quán)重去覆蓋這個(gè)樣式;
2,無論父組件樣式的權(quán)重多大,也可能無法修改子組件的樣式,除了子組件的根節(jié)點(diǎn)。
到此這篇關(guān)于vue中的scoped屬性的文章就介紹到這了,更多相關(guān)vue scoped屬性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue實(shí)現(xiàn)獲取后端接口API代碼片段(已封裝Service方法名)
Vue實(shí)現(xiàn)獲取后端接口API代碼片段(已封裝Service方法名),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07vue router總結(jié) $router和$route及router與 router與route區(qū)別
這篇文章主要介紹了vue router總結(jié) $router和$route及router與 router與route區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-07-07element?el-upload文件上傳覆蓋第一個(gè)文件的實(shí)現(xiàn)
這篇文章主要介紹了element?el-upload文件上傳覆蓋第一個(gè)文件的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03