成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何優雅地覆蓋組件庫樣式?

開發 前端
本文通過如何修改UI組件內部樣式為切入點,分析了幾種解法。了解了組合選擇器的優先級分數累加,以及在實際React、Vue項目用到的樣式隔離方案——CSS Module和Scoped的原理,最后是介紹了在樣式隔離的情況下,如何使用:global和深度作用選擇器做樣式覆蓋。

大家好,我是年年!組件庫的樣式覆蓋不掉,這應該是很多前端在工作中遇到過的問題。今天從實際案例出發分析原因,最后會給出在React和Vue項目中的最優解。

本文會講清:

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

先不講概念,直接從需求出發:我使用了Antd組件庫來展示一個日歷。

現在我想將當前日期上面的藍色邊框變成紫色。

可以試試你能不能實現。

不管是React還是Vue,整個Calendar是被封裝起來的,我們沒有辦法在組件外簡單加上style/class改動內部的樣式。

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

定位要覆蓋的樣式

首先用開發者工具定位對應的樣式:.ant-picker-calendar-date-today,這就是我們要修改的地方。

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

熟悉webpack的人應該知道,引入的CSS文件最終都會被style-loader處理。簡單來說,它的作用就是把CSS文件打包,放在style標簽內,最后塞進HTML中作為一個內部樣式表。不管是組件庫的樣式還是我們寫的自定義樣式都是這樣處理的。

我們要把組件庫的樣式先于自定義樣式引入,這樣自定義樣式才能有更高的優先級。

修改源文件

直接改組件庫的CSS源碼是最簡單粗暴的方法。打開你項目的node_modules文件夾,一層層點開,找到對應樣式文件,按照需求修改即可。

個人項目這樣處理確實可行,但是團隊合作時,同步別人本地的node_modules就比較麻煩,只能算一個60分解法。

全局CSS文件

之前提到,把自己寫的的CSS文件放在組件庫的樣式后面,可以保障自定義有更高優先級。只要重寫同名的樣式,理論上就能實現覆蓋組了。

但這樣??處理會發現并不起作用:

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

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

...

因為這里還涉及CSS組合選擇器的優先級。

基礎的優先級應該不用贅述:!important>內聯樣式>ID選擇器>類選擇器>標簽選擇器。(!important這種hack會導致項目不好維護,不提倡使用)

在這個基礎上還有五種組合選擇器要對優先級分數做累計,以類選擇器為例:

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

上面幾個規則看著很復雜,其實用的多的就是第一個后代選擇器,記住它就行。Antd組件庫用的就是它:

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

如果說一個類選擇器優先級分數是10分,那三個形成的后代選擇器就是30分。

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

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

需要完整重寫整個選擇器才能實現想要的效果。

這里補充一點,同樣也是組合選擇器,但并集選擇器(逗號)優先級不累計:.A, .B,選擇.A或者.B元素(可以是逗號+空格)

樣式隔離CSS Module和Scoped

上面我們引入自定義的全局CSS文件,實現了樣式的覆蓋,但是這種解法只能給80分。因為在實際工作中,項目Owner通常不允許使用全局CSS,這會造成樣式污染:你定義了一個樣式my_button,團隊其他人恰巧也命名為my_button,這就造成樣式沖突。

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

接下來會講清兩種樣式隔離的原理,以及使用樣式隔離時怎么覆蓋組件庫的樣式。

React的CSS Module

首先來了解一下CSS Module的原理。它的使用很簡單,在CSS文件加一個后綴.module,然后當做一個變量引入到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屬性都會加上一個哈希值作為命名空間。

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

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

但是在這種樣式隔離情況下,我們原本用作覆蓋的CSS也被加上了哈希值,就像下圖這樣,這時沒有辦法選中UI組件,覆蓋也就不會成功。

所以,React給我們提供了一個語法:global。它生效范圍內的樣式會被當作全局CSS。

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

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

SCSS或SASS中,還可以使用嵌套語法:

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

最后編譯出來的代碼如下:

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

借助:global語法,即使使用CSS Module進行樣式隔離也可以如愿實現覆蓋功能。

Vue中的Scoped

Vue中也有類似的樣式隔離功能,使用Scoped標記CSS部分,使用也很簡單??:

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

編譯出來的代碼如下??:

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

可以看到,它的原理和CSS Module不太一樣,Vue的Scoped會使CSS選擇器后加上一個中括號。

這并不是Vue獨創的語法,而是屬性選擇器。.myWrapper[data-v-2fc5154c]代表選擇擁有data-v-2fc5154c這個屬性的、同時是myButton類的HTML元素。只有這個文件內部的HTML元素才會被打上data-v-2fc5154c這個屬性。其余文件的HTML元素即使是myWrapper類,這個樣式也不會對他生效。

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

所以Vue提供了一個類似的語法:深度作用選擇器。

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

<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
/* 作用域內的CSS都沒有帶上屬性選擇器 */
.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“滲透”進組件內部。

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

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

結語

本文通過如何修改UI組件內部樣式為切入點,分析了幾種解法。了解了組合選擇器的優先級分數累加,以及在實際React、Vue項目用到的樣式隔離方案——CSS Module和Scoped的原理,最后是介紹了在樣式隔離的情況下,如何使用:global和深度作用選擇器做樣式覆蓋。

責任編輯:武曉燕 來源: 前端私教年年
相關推薦

2021-03-24 10:20:50

Fonts前端代碼

2024-11-13 16:37:00

Java線程池

2020-03-26 11:04:00

Linux命令光標

2021-01-18 13:17:04

鴻蒙HarmonyOSAPP

2021-05-12 22:07:43

并發編排任務

2021-01-28 14:53:19

PHP編碼開發

2022-05-24 06:07:48

JShack用戶代碼

2024-04-24 12:34:08

Spring事務編程

2020-10-22 10:15:33

優化Windows電腦

2021-09-08 08:34:37

Go 文檔Goland

2023-02-13 14:37:13

開發web瀏覽器

2018-08-20 10:40:09

Redis位圖操作

2020-12-08 08:08:51

Java接口數據

2017-12-14 14:17:08

Windows使用技巧手冊

2020-07-09 10:15:55

空值Bug語言

2020-09-25 11:30:20

Java判空代碼

2020-11-06 08:13:03

服務器Nodejs客戶端

2021-03-26 20:37:14

Prometheus監控指標

2020-02-05 14:05:21

Java技術數組

2020-04-10 10:22:12

Java判空編程語言
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩在线中文字幕 | 日韩图区 | 成人中文字幕在线 | 亚洲综合一区二区三区 | 国产成人综合一区二区三区 | 国内精品成人 | 久久久久99| 国产精品自产拍在线观看蜜 | 四虎影院免费在线播放 | 国产在线播 | 国产成人免费网站 | 国产精品 欧美精品 | 免费看黄视频网站 | 91国自视频 | 久久99一区二区 | 久久国产欧美日韩精品 | 国产精品久久毛片av大全日韩 | 日本久久一区 | 日韩一级黄色毛片 | 犬夜叉在线观看 | 日韩亚洲视频在线 | 久久夜色精品国产 | 日韩一区二区三区视频在线播放 | 国产成人综合久久 | av一级| 一区二区三区日韩精品 | 视频在线观看一区二区 | 蜜月aⅴ免费一区二区三区 99re在线视频 | 国产精品日韩欧美一区二区三区 | 琪琪午夜伦伦电影福利片 | 国产探花在线精品一区二区 | 日本在线一区二区 | 亚洲精品日韩在线 | 日本特黄a级高清免费大片 特黄色一级毛片 | 亚洲v日韩v综合v精品v | 久久久久久久久久久久91 | 91久久久精品国产一区二区蜜臀 | 一级毛片在线看 | 免费av电影网站 | 欧美精品一区二区在线观看 | 一区二区三区小视频 |