自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何優(yōu)雅地覆蓋組件庫(kù)樣式?

開發(fā) 前端
本文通過(guò)如何修改UI組件內(nèi)部樣式為切入點(diǎn),分析了幾種解法。了解了組合選擇器的優(yōu)先級(jí)分?jǐn)?shù)累加,以及在實(shí)際React、Vue項(xiàng)目用到的樣式隔離方案——CSS Module和Scoped的原理,最后是介紹了在樣式隔離的情況下,如何使用:global和深度作用選擇器做樣式覆蓋。

大家好,我是年年!組件庫(kù)的樣式覆蓋不掉,這應(yīng)該是很多前端在工作中遇到過(guò)的問(wèn)題。今天從實(shí)際案例出發(fā)分析原因,最后會(huì)給出在React和Vue項(xiàng)目中的最優(yōu)解。

本文會(huì)講清:

  • React中CSS Module的原理是什么?:global是做什么的?
  • Vue中Scoped的原理是什么?深度作用選擇器是什么?

先不講概念,直接從需求出發(fā):我使用了Antd組件庫(kù)來(lái)展示一個(gè)日歷。

現(xiàn)在我想將當(dāng)前日期上面的藍(lán)色邊框變成紫色。

可以試試你能不能實(shí)現(xiàn)。

不管是React還是Vue,整個(gè)Calendar是被封裝起來(lái)的,我們沒(méi)有辦法在組件外簡(jiǎn)單加上style/class改動(dòng)內(nèi)部的樣式。

import { Calendar } from 'antd';
...
<div className="myWrapper">
<Calendar class="custom"/>
</div>

定位要覆蓋的樣式

首先用開發(fā)者工具定位對(duì)應(yīng)的樣式:.ant-picker-calendar-date-today,這就是我們要修改的地方。

.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today {
border-color: #1890ff;
}

熟悉webpack的人應(yīng)該知道,引入的CSS文件最終都會(huì)被style-loader處理。簡(jiǎn)單來(lái)說(shuō),它的作用就是把CSS文件打包,放在style標(biāo)簽內(nèi),最后塞進(jìn)HTML中作為一個(gè)內(nèi)部樣式表。不管是組件庫(kù)的樣式還是我們寫的自定義樣式都是這樣處理的。

我們要把組件庫(kù)的樣式先于自定義樣式引入,這樣自定義樣式才能有更高的優(yōu)先級(jí)。

修改源文件

直接改組件庫(kù)的CSS源碼是最簡(jiǎn)單粗暴的方法。打開你項(xiàng)目的node_modules文件夾,一層層點(diǎn)開,找到對(duì)應(yīng)樣式文件,按照需求修改即可。

個(gè)人項(xiàng)目這樣處理確實(shí)可行,但是團(tuán)隊(duì)合作時(shí),同步別人本地的node_modules就比較麻煩,只能算一個(gè)60分解法。

全局CSS文件

之前提到,把自己寫的的CSS文件放在組件庫(kù)的樣式后面,可以保障自定義有更高優(yōu)先級(jí)。只要重寫同名的樣式,理論上就能實(shí)現(xiàn)覆蓋組了。

但這樣??處理會(huì)發(fā)現(xiàn)并不起作用:

/* src/demo.css */
.ant-picker-calendar-date-today {
border-color: purple; /* 覆蓋為紫色 */
}
// src/Demo.js

// 組件庫(kù)的樣式
import 'ant-design-vue/dist/antd.css';
// 自定義樣式
import './demo.css'
import { Calendar } from 'antd';
...
<div className="myWrapper">
<Calendar />
</div>
...

...

因?yàn)檫@里還涉及CSS組合選擇器的優(yōu)先級(jí)。

基礎(chǔ)的優(yōu)先級(jí)應(yīng)該不用贅述:!important>內(nèi)聯(lián)樣式>ID選擇器>類選擇器>標(biāo)簽選擇器。(!important這種hack會(huì)導(dǎo)致項(xiàng)目不好維護(hù),不提倡使用)

在這個(gè)基礎(chǔ)上還有五種組合選擇器要對(duì)優(yōu)先級(jí)分?jǐn)?shù)做累計(jì),以類選擇器為例:

  • 后代選擇器(空格):.A .B,選擇.A元素后的所有.B元素,
  • 子元素選擇器(大于號(hào)):.A>.B,選擇.A元素的直接后代中的.B元素
  • 相鄰兄弟選擇器(加號(hào)):.A+.B,選擇.A元素后緊鄰的第一個(gè)兄弟.B元素
  • 后續(xù)兄弟選擇器(~號(hào)):.A~.B,選擇.A元素后所有的兄弟.B元素
  • 交集選擇器(連在一起):.A.B選擇自身同時(shí)擁有.A和.B兩個(gè)屬性的元素

上面幾個(gè)規(guī)則看著很復(fù)雜,其實(shí)用的多的就是第一個(gè)后代選擇器,記住它就行。Antd組件庫(kù)用的就是它:

.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today {
border-color: #1890ff;
}

如果說(shuō)一個(gè)類選擇器優(yōu)先級(jí)分?jǐn)?shù)是10分,那三個(gè)形成的后代選擇器就是30分。

而自定義的樣式??只有10分,所以即使放在更后面引入,也不能成功覆蓋。

.ant-picker-calendar-date-today {
border-color: purple; // 覆蓋為紫色
}

需要完整重寫整個(gè)選擇器才能實(shí)現(xiàn)想要的效果。

這里補(bǔ)充一點(diǎn),同樣也是組合選擇器,但并集選擇器(逗號(hào))優(yōu)先級(jí)不累計(jì):.A, .B,選擇.A或者.B元素(可以是逗號(hào)+空格)

樣式隔離CSS Module和Scoped

上面我們引入自定義的全局CSS文件,實(shí)現(xiàn)了樣式的覆蓋,但是這種解法只能給80分。因?yàn)樵趯?shí)際工作中,項(xiàng)目Owner通常不允許使用全局CSS,這會(huì)造成樣式污染:你定義了一個(gè)樣式my_button,團(tuán)隊(duì)其他人恰巧也命名為my_button,這就造成樣式?jīng)_突。

我們需要給每個(gè)文件做樣式隔離,就好像是給它一個(gè)命名空間。通常使React項(xiàng)目使用的是用的是CSS Module,Vue項(xiàng)目使用Scoped標(biāo)記。

接下來(lái)會(huì)講清兩種樣式隔離的原理,以及使用樣式隔離時(shí)怎么覆蓋組件庫(kù)的樣式。

React的CSS Module

首先來(lái)了解一下CSS Module的原理。它的使用很簡(jiǎn)單,在CSS文件加一個(gè)后綴.module,然后當(dāng)做一個(gè)變量引入到JS文件中。

// src/Demo.js
import styles from './demo.module.css';
export default function Demo() {
return (
<div className={styles.myWrapper}>
<Calendar />
</div>
);
}
/* src/demo.module.css */
.myWrapper {
border: 5px solid black;
}

被編譯后??,插入的樣式表和元素的class屬性都會(huì)加上一個(gè)哈希值作為命名空間。

<style>
.demo_myWrapper__Hd9Qg {
border: 5px solid black;
}
</style>
<div class="demo_myWrapper__Hd9Qg">
...
</div>

可以看到,原本的CSS選擇器和HTML元素類名都從myWrapper變成了demo_myWrapper__Hd9Qg,前面加上了文件名,后面加上了哈希值,這樣就能保障樣式只在當(dāng)前這個(gè)文件下生效了。

但是在這種樣式隔離情況下,我們?cè)居米鞲采w的CSS也被加上了哈希值,就像下圖這樣,這時(shí)沒(méi)有辦法選中UI組件,覆蓋也就不會(huì)成功。

所以,React給我們提供了一個(gè)語(yǔ)法:global。它生效范圍內(nèi)的樣式會(huì)被當(dāng)作全局CSS。

具體使用如下,在CSS文件中,使用:global包裹希望全局生效的樣式

:global(.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today) {
border-color:purple; /* 覆蓋為紫色 */
}

SCSS或SASS中,還可以使用嵌套語(yǔ)法:

:global {
.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today {
border-color:purple;
}
}

最后編譯出來(lái)的代碼如下:

/* 加上了哈希*/
.demo_myWrapper__Hd9Qg {
border: 5px solid black;
}
/* :global作用域下都不會(huì)加上哈希*/
.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today {
border-color:purple;
}

借助:global語(yǔ)法,即使使用CSS Module進(jìn)行樣式隔離也可以如愿實(shí)現(xiàn)覆蓋功能。

Vue中的Scoped

Vue中也有類似的樣式隔離功能,使用Scoped標(biāo)記CSS部分,使用也很簡(jiǎn)單??:

<style scoped>
.myWrapper{
border: 5px solid black
}
</style>
...
<div class="myWrapper" >
<Calendar />
</div>
...

編譯出來(lái)的代碼如下??:

<style>
.myWrapper[data-v-2fc5154c] {
border: 5px solid black
}
</style>
<div class="myWrapper" data-v-2fc5154c>
...
</div>

可以看到,它的原理和CSS Module不太一樣,Vue的Scoped會(huì)使CSS選擇器后加上一個(gè)中括號(hào)。

這并不是Vue獨(dú)創(chuàng)的語(yǔ)法,而是屬性選擇器。.myWrapper[data-v-2fc5154c]代表選擇擁有data-v-2fc5154c這個(gè)屬性的、同時(shí)是myButton類的HTML元素。只有這個(gè)文件內(nèi)部的HTML元素才會(huì)被打上data-v-2fc5154c這個(gè)屬性。其余文件的HTML元素即使是myWrapper類,這個(gè)樣式也不會(huì)對(duì)他生效。

回到相同的問(wèn)題,假如Vue項(xiàng)目在使用了Scoped做樣式隔離,我們用于覆蓋的樣式也會(huì)加上屬性選擇器,但是UI組件內(nèi)部的HTML元素都沒(méi)有該屬性??。

所以Vue提供了一個(gè)類似的語(yǔ)法:深度作用選擇器。

使用很簡(jiǎn)單,把要“滲透“進(jìn)組件內(nèi)部的樣式前面加上>>>,作用域內(nèi)的CSS樣式都不會(huì)帶上哈希值作為屬性選擇器。

<style scoped>
.myWrapper>>>
.ant-picker-calendar-full
.ant-picker-panel
.ant-picker-calendar-date-today{
border-color:purple
}
</style>
<template>
<div class="myWrapper" >
<Calendar />
</div>
</template>

編譯后??

<style>
.myWrapper[data-v-2fc5154c]
.ant-picker-calendar-full
.ant-picker-panel
/* 作用域內(nèi)的CSS都沒(méi)有帶上屬性選擇器 */
.ant-picker-calendar-date-today {
border-color:purple
}
</style>

<div class="myWrapper" data-v-2fc5154c>
<div class="ant-picker-calendar-full" data-v-2fc5154c>
<div class="ant-picker-date-panel">
<td class="ant-picker-cell-today"></td>
</div>
</div>
</div>

借助深度作用選擇器,可以將要用于覆蓋CSS“滲透”進(jìn)組件內(nèi)部。

也可以將>>>寫成/deep/或者::v-deep。

相較于React的:global,Vue的深度作用選擇器是一種更優(yōu)秀的方案,它必須要一個(gè)前導(dǎo)(也就是上面例子中的.myWrapper選擇器),前導(dǎo)依舊會(huì)被打上哈希值作為屬性選擇器,要滲透進(jìn)去的樣式實(shí)際上是作為它的子選擇器,只在當(dāng)前這個(gè)文件下生效,徹底避免造成全局污染。

結(jié)語(yǔ)

本文通過(guò)如何修改UI組件內(nèi)部樣式為切入點(diǎn),分析了幾種解法。了解了組合選擇器的優(yōu)先級(jí)分?jǐn)?shù)累加,以及在實(shí)際React、Vue項(xiàng)目用到的樣式隔離方案——CSS Module和Scoped的原理,最后是介紹了在樣式隔離的情況下,如何使用:global和深度作用選擇器做樣式覆蓋。

責(zé)任編輯:武曉燕 來(lái)源: 前端私教年年
相關(guān)推薦

2021-03-24 10:20:50

Fonts前端代碼

2024-11-13 16:37:00

Java線程池

2021-01-28 14:53:19

PHP編碼開發(fā)

2022-05-24 06:07:48

JShack用戶代碼

2024-04-24 12:34:08

Spring事務(wù)編程

2020-03-26 11:04:00

Linux命令光標(biāo)

2021-01-18 13:17:04

鴻蒙HarmonyOSAPP

2021-05-12 22:07:43

并發(fā)編排任務(wù)

2021-09-08 08:34:37

Go 文檔Goland

2020-10-22 10:15:33

優(yōu)化Windows電腦

2020-12-08 08:08:51

Java接口數(shù)據(jù)

2018-08-20 10:40:09

Redis位圖操作

2023-02-13 14:37:13

開發(fā)web瀏覽器

2017-12-14 14:17:08

Windows使用技巧手冊(cè)

2020-04-10 10:22:12

Java判空編程語(yǔ)言

2022-03-25 06:26:57

WiFi密碼路由器

2022-08-11 11:09:38

線上問(wèn)題程序員

2020-02-05 14:05:21

Java技術(shù)數(shù)組

2020-09-25 11:30:20

Java判空代碼

2020-11-06 08:13:03

服務(wù)器Nodejs客戶端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)