前言
在我們前端的開發中經常會使用到各種 ui 框架 下面這兩個是比較火的,也是我常用的兩個ui框架。
問題描述
但是在使用框架的時候難免會遇到需要改變組件中的一些樣式,當然如果我們所有頁面的組件樣式都是統一的話,我們可以進行全局設置樣式,但是如果我們僅僅在一個頁面中需要個性化的樣式設置,我們平常會下面這樣操作:
<style lang="less" scoped>
#main {width: 100%;height: 90%;
}
.ivu-form .ivu-form-item-label {color: #fff;
}
.ivu-table th {height: 60px !important;
}
.ivu-table td {height: 45px !important;
}
.conLeft {width: 78%;height: 100%;padding: 10px;position: relative;img {width: 100%;height: 100%;}.smaBox {cursor: pointer;position: absolute;width: 40px;height: 40px;}
}
</style>
不難看出我們上面的很多類名就是我們組件中自帶的,我們只有通過這些類名去更改我們當前頁面組件呈現的樣式,但是因為我們在當前頁面中去編寫的樣式只想讓其應用在當前的頁面中,所以我們在style中去添加了scoped屬性,關于scoped屬性的講解我們放到下面去講解;
先回到我們上面的代碼中,看似沒有任何問題我們去通過類名改變組件的樣式,但是他不會生效,就是因為scoped屬性導致的問題,在我們的Vue項目中scoped屬性真的很好用,為我們避免了組件之間的樣式覆蓋,使我們定的樣式不會造成全局的污染!
解決辦法 - 樣式穿透即可
首先我們要搞明白添加上scoped屬性后發生了什么,如果您著急解決問題可以直接看我們這個小節的問題解決,如果您想知其然知其所以然,那么您現在可以先去看文章的下一小節——scoped屬性的原理。
使用樣式穿透去解決 scoped 帶來的問題,樣式穿透有四種形式:
不太推薦第一種寫法,不同瀏覽器的展示形式不一樣,容易出問題,2、3、4這幾種都是有預處理器(less, scss, sass)的寫法,推薦大家使用第二、三種,
- stylus的樣式穿透 使用 >>>
- /deep/
- ::v-deep
- 去掉scoped
將scoped屬性去掉。雖然很方便 但是失去了樣式的保護,我們就需要用原始的方法保護該組件的樣式作用域,可通過后臺選擇器等等方式實現樣式的保護,使其不受污染。好像更麻煩了。
上面我通過使用第二種方式 輕松實現了
scoped屬性的原理
為了使樣式私有化(模塊化),不對全局造成污染,可以在style標簽上添加scoped屬性以表示它的只屬于當下的模塊,這是一個非常好的舉措
我們可能只了解他的作用就是為了讓當前組中的style中的樣式,僅僅對當前組件生效,對原理可能不太懂,那下面小編就帶大家梳理一下scoped的原理。
scoped的用法
<template><div class="box">歡迎您的光臨</div>
</template><style lang="less" scoped>.box{background-color:green;}
</style>
- 從上面的代碼中我們可以看出我們的scoped屬性就是直接寫到我們的style標簽當中,使用就是這么簡單
設置scoped屬性后發生了什么
設置上了scoped 實際上我們是將代碼通過 PostCss 進行了轉換,下面我們進行一下對比
PostCss是一個樣式處理工具,它通過自定義的插件和工具生態體系來重新定義css,有興趣的同學可以去了解一下關于PostCss中的一些常用插件,讓你的css更哇塞
轉換前:
<template><div class="box">歡迎您的光臨</div>
</template><style lang="less" scoped>.box{background-color:green;}
</style>
轉換后:
<template><div class="box" data-v-21aa888a>歡迎您的光臨</div>
</template><style>.example[data-v-21aa888a] {color: red;}
</style>
- 上面對比后大家應該就懂了是怎么回事了吧,其實說白了加上scoped后vue編譯過程中會生成一個唯一的data-xxx標志,樣式后面會跟上該標志,以避免污染全局樣式
- 在父組件中設置了scoped中的樣式 如果該組件中有子組件 那子組件的根元素中也會繼承父組件中生成的style的唯一標識
慎用scoped
上面我們看到了scoped這個屬性很香,其實他隱藏了很多坑
- 大家都知道css樣式有一個優先級的說法,scoped的這一操作,雖然達到了組件樣式模塊化的目的,但是會造成一種后果:每個樣式的權重加重了:理論上我們要去修改這個樣式,需要更高的權重去覆蓋這個樣式。這是增加復雜度的其中一個維度,所以如果要達到修改樣式的目的,就必須加重我們要修改樣式的權重(增加選擇器層級,ID選擇器,并列選擇器,impotant等)
- 還有一種情況就是我們的兩個組件中均含有scoped 而且一個組件中包含了另一個組件,所以在Dom渲染的時候會在dom節點上加上很多唯一style的標識,有的是繼承的,有的是自己組件的,所以我們在修改樣式的時候還是會涉及到上面所說的權重問題,如果做不好可能會出現尷尬的問題就是自己的組件修改不了自己組件的樣式哈哈
- 最后的問題就是我們上面拋出的問題,當我們設置此屬性后我們想要改變組件中的樣式是改變不了的,當然我們可以通過強大樣式穿透進行解決!