vue中的css作用域、vue中的scoped坑點


一、css作用域

  之前一直很困擾css的作用域問題,即使是模塊化編程下,在對應的模塊的js中import css進來,這個css仍然是全局的。導致在css中需要加上對應模塊的html的id/class 使用css選擇器 保證css的作用域不會變成全局 而被其它模塊的css污染。

  在vue中引入了scoped這個概念,scoped的設計思想就是讓當前組件的樣式不會修改到其它地方的樣式,使用了data-v-hash的方式來使css有了它對應模塊的標識,這樣寫css的時候不需要加太多額外的選擇器,方便很多。

  但是要注意scoped的作用域,因為權重的問題,如果是在子組件使用了scoped,那么在父組件中是不能直接修改子組件的樣式的,需要在父組件中使用vue的深度作用選擇器。

.parent >>> .children{ /* ... */ } .parent /deep/ .children{ /* ... */ }

二、scoped坑點

  今天在覆蓋iview組件樣式的時候發現一個問題,就是無法覆蓋組件原有的樣式,最后在github的issue中找到了答案: 不要使用scoped屬性。於是我查找了下關於scoped的文章。

  我們假設把這種組件叫做模塊私有組件,其他的未加scoped的叫做模塊一般組件。通過查看DOM結構發現:vue通過在DOM結構以及css樣式上加唯一不重復的標記,以保證唯一,達到樣式私有化模塊化的目的。

//valChange.less(使用了嵌套規則)
#valueSlide{ .bigSlider .ivu-slider-wrap{ height: 6px; } .bigSlider .ivu-slider-bar { height: 6px; } .bigSlider .ivu-slider-button{ width: 14px; height: 14px; } } //html部分
<style lang="less" scoped> @import "./valChange.less"; </style>
<div class="valid-panel">
    <div class="containerBox">
        <div id="valueSlide" v-bind:style="validStyle">
            <Slider ></Slider>
        </div>
    </div>
</div>

  也就是我們在style中使用scoped屬性會出現下面的情況:

  HTML部分:

  CSS部分:

  從上面的字可以看出,添加了scoped屬性的組件,為了達到組件樣式模塊化,做了兩個處理:

  • 給HTML的DOM節點加一個不重復data屬性(形如:data-v-19fca230)來表示他的唯一性
  • 在每句css選擇器的末尾(編譯后的生成的css語句)加一個當前組件的data屬性選擇器(如[data-v-2311c06a])來私有化樣式

  那么問題來了: 對於當前組件下調用的其他組件,data屬性只會添加到第一層HTML中

  對於我們想覆蓋的樣式則無法起到作用:(在瀏覽器調試中手動添加 [data-v-19fca230] 屬性后可以匹配)

  解決方案:

  不使用scoped屬性,更多詳細介紹可以參考這篇文章

  總結一下scoped三條渲染規則:

  1、給HTML的DOM節點加一個不重復data屬性(形如:data-v-19fca230)來表示他的唯一性

  2、在每句css選擇器的末尾(編譯后的生成的css語句)加一個當前組件的data屬性選擇器(如[data-v-19fca230])來私有化樣式

  3、如果組件內部包含有其他組件,只會給其他組件的最外層標簽加上當前組件的data屬性

  問題補充:

  1、如果不使用scoped,如何解決樣式全局污染?

  推薦使用scoped推動組件私有化,文章所提到的不使用僅出現在已有UI庫的樣式覆蓋上(當然人家用了scoped 那就很難辦了)。

  首先,解決組件樣式全局污染,也就是我們在這里不使用scoped 覆蓋了樣式,那么我們在其他地方調用該組件就會被覆蓋。那么我們在使用組件的時候對組件給一個類名 或者其他甄別屬性(id),覆蓋樣式就針對該類名進行重寫樣式。

  其次,解決其他樣式全局污染,如果我們通過:

<style lang="less"> @import "./test.less"; </style>

  引進樣式,那么不使用scoped"./test.less" 中的其他類名樣式可能會污染全局,我這里用一個比較笨的方法處理:在模板中使用兩次<style></style> 標簽:

<style lang="less" scoped> @import "./test.less"; </style>
<style lang="less">
    //你的覆蓋樣式
</style>

  這樣既覆蓋了樣式,其他樣式不會被覆蓋到全局,感興趣的同學可以自己試一試。(注意兩個標簽的順序)。

  官網 vue-loader 中提到每個vue模板中可以有多個<style></style>標簽,所以上面的寫法是沒有問題的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM