一文徹底搞懂Vue中scoped和/deep/原理
背景
我們做 Vue 項(xiàng)目在組件里寫 css 的時(shí)候,經(jīng)常會給 <style>
標(biāo)簽加上 scoped
,比如這樣: <style lang="less" scoped>
,這樣寫出來的 css 就是局部的,不會影響其他組件。
另外,假設(shè)我們在自己的組件中引入了一個(gè)子組件,并且希望在我的組件中修改子組件中的樣式,由于我們用了 scoped
,直接修改是不生效的。去掉 scoped
是可以的,不過沒了局部 css
風(fēng)險(xiǎn)不可控。有一種更好的方式,用深度選擇器修改,比如 less
中的 /deep/
。用過組件庫(如 element ui
)的朋友,在覆蓋組件庫樣式的時(shí)候應(yīng)該會經(jīng)常用到深度選擇器 /deep/
。
基于以上兩點(diǎn),我們來聊一聊:
- 為什么
scoped
可以形成局部css
?原理是什么? - 為什么
/deep/
可以跨組件修改css
?原理是什么?
scoped 形成局部 css 原理
先看一張圖:
我們審查 html
元素時(shí)發(fā)現(xiàn)多了很多類似 data-v-f321cf6
屬性,這些屬性其實(shí)就是 scoped
hash
出來的。
再來看一張頁面生成的 css
截圖:
仔細(xì)看第一張圖標(biāo)記了兩種顏色,他們分別對應(yīng)兩種 hash
屬性值: data-v-f5321cf6
和 data-v-6a6ef68c
,其實(shí)這里就是兩個(gè)不同的組件生成的兩個(gè)不同的值,每個(gè)加過 scoped
的組件生成的值都是唯一的。
結(jié)合兩張圖,不難發(fā)現(xiàn) scoped
形成局部 css
的原理其實(shí)很簡單,就是先給元素加上 hash
出來的屬性,再通過屬性選擇器來選擇這些元素,由于每個(gè)組件 hash
出來的屬性值都是唯一的, css
屬性選擇器選出來的元素當(dāng)然也是組件級的了,因?yàn)樾纬闪私M件內(nèi)局部 css
。
/deep/ 跨組件修改 css 原理
一個(gè)例子
一個(gè)列表頁面 ,需要在數(shù)據(jù)為空的時(shí)候展示空白頁,這個(gè)空白頁我們引入的是第三方組件庫的空白頁組件 <no-data>
。
假設(shè)我們現(xiàn)在要修改空白頁組件中圖片的寬高, <no-data>
不支持傳入寬高,并且我們無法改動這個(gè)第三方組件,只能在列表頁通過 css
覆蓋空白頁組件的樣式。
我們第一時(shí)間想到改樣式嘛,這還不簡單,于是寫下:
<style lang="less" scoped> .no-data{ img { width: 200px; height: 200px; } } </style>
自信滿滿的點(diǎn)開瀏覽器查看效果,發(fā)現(xiàn)設(shè)置的寬高并沒起到作用,空白頁圖片還是默認(rèn)的偏大。
仔細(xì)一想,父組件用了 scoped
是不能直接改子組件內(nèi)樣式的,得用 /deep/
,于是乎有了下面的代碼:
<style lang="less" scoped> .no-data{ /deep/img { width: 200px; height: 200px; } } </style>
再查看效果:
生效了,圖片小了很多!
我們再來審查一下頁面渲染出來的代碼,沒加 /deep/
的:
注意看 css
部分,這里的選擇器是 .acl-nodata img[data-v-6a6ef68c]
,這里的 data-v-6a6ef68c
屬性是 <no-data>
組件中的 scoped
生成的。
接著往下看,加上 /deep/
后的:
還是重點(diǎn)看 css
部分,這里的選擇器是 .integral-detail .no-data[data-v-f5321cf6] img
,這里的 data-v-f5321cf6
是列表頁的 scoped
生成的。
核心區(qū)別在于: img[data-v-6a6ef68c]
和 .no-data[data-v-f5321cf6] img
/deep/ 原理
通過上面的例子,我們可以分析出,在使用了 /deep/
選擇器后,會把當(dāng)前元素 img
的 [data-v-6a6ef68c]
干掉,并通過他的父級(準(zhǔn)確的說是 img
元素所屬空白頁組件的根元素 <div ></div>
),來查找到 img
,也就是通過 .no-data[data-v-f5321cf6] img
來定位到 img
元素。
因?yàn)槲覀兊拇a是在列表頁寫的,列表頁 hash
出來的屬性是 [data-v-f5321cf6]
,在我們使用 /deep/
之前, img
的 hash
是 [data-v-6a6ef68c]
,在列表頁中的 css
代碼當(dāng)然是識別不到空白頁組件的 [data-v-6a6ef68c]
,所以修改寬高不生效。使用 /deep/
之后,通過 .no-data[data-v-f5321cf6] img
,由于 [data-v-f5321cf6]
本身就是列表 hash
出來的,自然是可以識別的,修改寬高自然也就生效了。
為了加深理解,這里再提一點(diǎn),仔細(xì)看 <div ></div>
這一塊的 html
代碼,你會發(fā)現(xiàn)它是同時(shí)具有 [data-v-f5321cf6]
和 [data-v-6a6ef68c]
兩種屬性,因?yàn)?<no-data>
組件的根元素是 <div ></div>
,在列表頁引入 <no-data>
, <div ></div>
也相當(dāng)于是列表中的一個(gè)元素,所以 scoped
也會給它 hash
上 [data-v-f5321cf6]
。 (這一塊在實(shí)際開發(fā)中,有些朋友會搞一些騷操作,比如在父組件和子組件同時(shí)改 .no-data
)
以上就是一文徹底搞懂Vue中scoped和/deep/原理的詳細(xì)內(nèi)容,更多關(guān)于Vue scoped和/deep/原理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue實(shí)現(xiàn)將數(shù)據(jù)庫中帶html標(biāo)簽的內(nèi)容輸出(原始HTML(Raw HTML))
今天小編就為大家分享一篇Vue實(shí)現(xiàn)將數(shù)據(jù)庫中帶html標(biāo)簽的內(nèi)容輸出(原始HTML(Raw HTML)),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10詳解Vue的常用指令v-if, v-for, v-show,v-else, v-bind, v-on
Vue.js的指令是以v-開頭的,它們作用于HTML元素,指令提供了一些特殊的特性。這篇文章主要介紹了Vue的常用指令v-if, v-for, v-show,v-else, v-bind, v-on 的相關(guān)知識,需要的朋友可以參考下2018-10-10vue 界面刷新數(shù)據(jù)被清除 localStorage的使用詳解
今天小編就為大家分享一篇vue 界面刷新數(shù)據(jù)被清除 localStorage的使用詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09vue2.0基于vue-cli+element-ui制作樹形treeTable
這篇文章主要介紹了vue2.0基于vue-cli+element-ui制作樹形treeTable,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04vue+axios 前端實(shí)現(xiàn)登錄攔截的兩種方式(路由攔截、http攔截)
本文通過實(shí)例代碼給大家介紹了vue+axios 前端實(shí)現(xiàn)登錄攔截的方法,主要通過路由攔截和http攔截,具體實(shí)例代碼大家跟隨小編一起通過本文學(xué)習(xí)吧2018-10-10