在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