vue中修改子組件(或第三方組件庫)樣式


一、問題敘述

  項目里需要新添加一個表單頁面,里面就只是幾個select,這個幾個select是原本封裝好的組件,有自己原本的樣式,而這次的原型圖卻沒有和之前的樣式統一起來,需要微調一下,這里就涉及到父組件修改子組件的樣式。不想混用本地和全局樣式,所以選擇了>>>,但是並不起作用,就換成/deep/,其實到這里我也沒有繼續深入這個知識點,因為在瀏覽器里預覽后已經實現了原型圖的樣式,直到打包在手機上測試,發現問題,在手機上瀏覽並沒有將樣式修改過來。如下圖:

 

問題:①為什么使用>>>不起作用?②為什么我使用了/deep/卻沒有成功的在手機上將樣式修改過來?

二、相關知識點

  ㈠關於vue中使用scoped屬性

在vue組件中,在style標簽中添加scoped屬性,這樣在這里定義的css只作用於當前組件中的元素,可使組件之間的樣式不會相互污染,使樣式私有化。比如在父組件內使用子組件,父組件的樣式不會滲透到子組件中。

  Ⅰ、在加上scoped后,會為DOM節點自動添加一個唯一的屬性(data-v-f3f3eg9后面這串數字像是獨一無二的hash值),以保證其唯一性。同時在相應的css選擇器末尾,也加上了當前組件的data-v-f3f3eg9屬性,來使其私有化。

如Vue Loader中所給出的代碼示例:

<template>
  <div class="example">hi</div>
</template>

<style scoped>
.example {
  color: red;
}
</style>

轉化后:

<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>

<style>
.example[data-v-f3f3eg9] {
  color: red;
}
</style>

  ㈡關於深度作用選擇器:/deep/(>>>)

  使用了scoped后,盡管實現組件樣式的私有化,但在我們實際的項目中,在很多地方使用重復的子組件或其他的樣式庫時,在個別地方需要微調樣式,這個時候不能直接改子組件樣式,而且在父組件里的樣式又不能滲透到子組件去。這個時候文檔中有一句話:

不過一個子組件的根節點會同時受其父組件的 scoped CSS 和子組件的 scoped CSS 的影響。這樣設計是為了讓父組件可以從布局的角度出發,調整其子組件根元素的樣式。

  所以還是有辦法解決剛才那個問題的,當我們希望 scoped 樣式中的一個選擇器能夠作用得“更深”,例如影響子組件,你可以使用 >>> 操作符,編譯后會在相應的選擇器后面增加獨有的屬性;如下:

<style scoped>
.a >>> .b { /* ... */ }
</style>

上述代碼將會編譯成:

.a[data-v-f3f3eg9] .b { /* ... */ }

  在這里需要注意的是,有些像 Sass 、scss之類的預處理器無法正確解析 >>>。這種情況下我們可以使用 /deep/ 或 ::v-deep 操作符來取代>>>,這是兩個都是 >>> 的別名,同樣可以正常工作。如下:

<style lang='scss' scoped>
.a {
    /deep/ .b{
                /* ... */
    }
}
</style>

三、問題解決

  ①為什么使用>>>不起作用?

  因為這個項目使用的scss,所以無法正常解析>>>,所以在父組件沒有滲透下去。

.pop-content {
   .input-wrapper >>>  .form-item {
    .form-label {
     /*...*/
  }

  在瀏覽器查看轉換的結果發現,還是原本組件的樣式,我新定義的並沒有出現。如下圖:

  ②為什么我使用了/deep/卻沒有成功的在手機上將樣式修改過來?

  因為引用的這個子組件里還包裹了一層子組件,我使用了兩個/deep/,不理解/deep/的實現原理,自以為每一個組件都要滲透一次。

/*錯誤代碼:寫了兩次/deep */
.pop-content {
  /deep/ .input-wrapper /deep/  .form-item {
      ...
  } 
 }

轉換后在瀏覽器看到的代碼,發現第二個是無法轉換的。

.pop-content[data-v-b93cf8e0] .input-wrapper /deep/ .form-item {}

 

/*修改后的代碼*/
.pop-content {  
     .input-wrapper /deep/  .form-item {  
    }
  }​

/*編譯轉換后的代碼*/
 .pop-content .input-wrapper[data-v-b93cf8e0] .form-item 

  ③隨之而來第三個問題,我只寫一個/deep/的話,我寫在哪個位置呢,是不是寫在哪都行,它們之間有什么區別。

  ⅰ嘗試一:將/deep/寫在input-wrapper后面

.pop-content { 
   .input-wrapper /deep/  .form-item {
    padding: 0.4rem 2rem 0.3rem 1.5rem;
    .form-label {
      -webkit-box-flex: 0;
      -ms-flex: 0 0 8rem;
      flex: 0 0 50%;
      font-size: 15px;
      color: black;
      position: relative;
    }
  }

轉換后的樣式代碼:原本的樣式已經失效了,並在input-wrapper后面添加了相應唯一的data-v屬性值。

  ⅱ嘗試二:將/deep/寫在pop-content后面

.pop-content {
  /deep/  .input-wrapper .form-item {
    padding: 0.4rem 2rem 0.3rem 1.5rem;
    .form-label {
      -webkit-box-flex: 0;
      -ms-flex: 0 0 8rem;
      flex: 0 0 50%;
      font-size: 15px;
      color: black;
      position: relative;
    }
  }

轉換后的樣式代碼:原本的樣式已經失效了,並在pop-content后面添加了相應唯一的data-v屬性值。

  ⅲ嘗試三:將/deep/寫在form-item或者form-label后面,均不起作用。看了一下DOM結構,我覺得可能是因為這樣做的css的優先級並沒有比原來的高,所以沒法改變。還有就是這個子組件內部的組件嵌套也比較復雜,所以從最外面的父組件看不出,所以對/deep/位置的放置對其優先級的影響還是比較大的。大致這樣理解。

 


免責聲明!

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



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