在vue組件中可以使用scoped的css來實現樣式的模塊化,避免對其他組件的影響;而想在父組件中修改子組件的樣式時往往由於scoped的原因,導致樣式不生效,需要使用深度選擇器進行樣式穿透。
那么本文就來看看具體是怎么實現的。
1.准備案例
父組件App.vue
<template>
<div class="container">
<h3 class="title">Hello Vue</h3>
<card />
</div>
</template>
<script>
import Card from './Card.vue';
export default {
components: { Card }
}
</script>
<style scoped>
.container {
width: 300px;
height: 300px;
padding-top: 10px;
background-color: #efefef;
}
.container .title {
color: #709b90;
text-align: center;
}
.card {
border: 2px solid#CDC9C9;
margin-left: 50px;
}
</style>
子組件Card.vue
<template>
<div class="card">
<div class="title">Vue Cli</div>
<div class="list">
<div class="item">vue serve</div>
<div class="item">vue build</div>
</div>
</div>
</template>
<style scoped>
.card {
width: 200px;
height: 200px;
}
.title {
height: 30px;
line-height: 30px;
color: #FFDEAD;
padding-left: 10px;
background-color: #87CEFA;
}
.item {
height: 30px;
line-height: 30px;
padding-left: 10px;
background-color: #FFE4E1;
}
</style>
效果如下:

2.scoped的實現
把組件進行編譯,查看一下:
編譯后的html:
<div data-v-4fe14a3c="" class="container">
<h3 data-v-4fe14a3c="" class="title">Hello Vue</h3>
<div data-v-119ff0e6="" data-v-4fe14a3c="" class="card">
<div data-v-119ff0e6="" class="title">Vue Cli</div>
<div data-v-119ff0e6="" class="list">
<div data-v-119ff0e6="" class="item">vue serve</div>
<div data-v-119ff0e6="" class="item">vue build</div>
</div>
</div>
</div>
需要說明一下:每次編譯后vue組件中的dom會由js動態生成,所以需要用瀏覽器打開編譯后的html,再用開發者工具查看
編譯后的css:
.card[data-v-119ff0e6] {
width: 200px;
height: 200px
}
.title[data-v-119ff0e6] {
height: 30px;
line-height: 30px;
color: #ffdead;
padding-left: 10px;
background-color: #87cefa
}
.item[data-v-119ff0e6] {
height: 30px;
line-height: 30px;
padding-left: 10px;
background-color: #ffe4e1
}
.container[data-v-4fe14a3c] {
width: 300px;
height: 300px;
padding-top: 10px;
background-color: #efefef
}
.container .title[data-v-4fe14a3c] {
color: #709b90;
text-align: center
}
.card[data-v-4fe14a3c] {
border: 2px solid#CDC9C9;
margin-left: 50px
}
編譯后dom元素都會添加上data-v-hashxxxx的屬性,而樣式中的選擇器也被添加上了data-v-hashxxxx的屬性,每個組件的data-v-hashxxxx是一樣的因此限制了樣式的作用范圍。另外子組件的最外層也會被添加上父組件的data-v-hashxxxx,同時含有父組件、子組件的data-v-hashxxxx屬性,所以父組件中的樣式會對子組件的最外層元素起作用,如上面的.card定義的樣式。
3.父組件中直接修改子組件的樣式
App.vue中添加:
.card .title {
color: #eee;
}
在父組件中直接修改子組件中(非最外層)元素的樣式,然而並不起作用,來看看怎么回事吧。
再次編譯,查看編譯后的html:
<div data-v-7a169200="" class="container">
<h3 data-v-7a169200="" class="title">Hello Vue</h3>
<div data-v-119ff0e6="" data-v-7a169200="" class="card">
<div data-v-119ff0e6="" class="title">Vue Cli</div>
<div data-v-119ff0e6="" class="list">
<div data-v-119ff0e6="" class="item">vue serve</div>
<div data-v-119ff0e6="" class="item">vue build</div>
</div>
</div>
</div>
編譯后的css:
.card[data-v-119ff0e6] {
width: 200px;
height: 200px
}
.title[data-v-119ff0e6] {
height: 30px;
line-height: 30px;
color: #ffdead;
padding-left: 10px;
background-color: #87cefa
}
.item[data-v-119ff0e6] {
height: 30px;
line-height: 30px;
padding-left: 10px;
background-color: #ffe4e1
}
.container[data-v-7a169200] {
width: 300px;
height: 300px;
padding-top: 10px;
background-color: #efefef
}
.container .title[data-v-7a169200] {
color: #709b90;
text-align: center
}
.card[data-v-7a169200] {
border: 2px solid#CDC9C9;
margin-left: 50px
}
.card .title[data-v-7a169200] {
color: #eee
}
在父組件內編寫的樣式經編譯后都會帶上和父組件元素一樣的data-v-hashxxxx,只對父組件范圍內的元素起作用,觸及不到引入的子組件的內部,也就是說無法覆蓋子組件的樣式。
4.使用 >>> 深度選擇器進行樣式穿透
在App.vue中添加樣式,修改子組件的title及列表項的字體顏色:
.card >>> .title {
color: #eee;
}
.container .card >>> .list .item {
color: #FF6347;
}
這次起作用了,效果如下:

再查看一下編譯后的結果,編譯后的html:
<div data-v-dba577b2="" class="container">
<h3 data-v-dba577b2="" class="title">Hello Vue</h3>
<div data-v-119ff0e6="" data-v-dba577b2="" class="card">
<div data-v-119ff0e6="" class="title">Vue Cli</div>
<div data-v-119ff0e6="" class="list">
<div data-v-119ff0e6="" class="item">vue serve</div>
<div data-v-119ff0e6="" class="item">vue build</div>
</div>
</div>
</div>
編譯后的css:
.card[data-v-119ff0e6] {
width: 200px;
height: 200px
}
.title[data-v-119ff0e6] {
height: 30px;
line-height: 30px;
color: #ffdead;
padding-left: 10px;
background-color: #87cefa
}
.item[data-v-119ff0e6] {
height: 30px;
line-height: 30px;
padding-left: 10px;
background-color: #ffe4e1
}
.container[data-v-dba577b2] {
width: 300px;
height: 300px;
padding-top: 10px;
background-color: #efefef
}
.container .title[data-v-dba577b2] {
color: #709b90;
text-align: center
}
.card[data-v-dba577b2] {
border: 2px solid#CDC9C9;
margin-left: 50px
}
.card[data-v-dba577b2] .title {
color: #eee
}
.container .card[data-v-dba577b2] .list .item {
color: tomato
}
可以看到,使用樣式穿透后編譯后沒有在選擇器末尾添加data-v-hashxxxx屬性,而是把data-v-hashxxxx添加到了>>>的位置,這樣就能夠選中子組件中的元素了。
補充一下
不同css預處理器中樣式穿透的寫法:
css: >>>
less/sass: /deep/
scss: ::v-deep
