Bagaimana untuk mengatasi gaya perpustakaan komponen? Artikel berikut akan memperkenalkan kepada anda cara mengatasi gaya perpustakaan komponen secara elegan dalam projek React dan Vue saya harap ia akan membantu anda.
Gaya pustaka komponen tidak boleh ditimpa Ini sepatutnya menjadi masalah yang dihadapi oleh ramai pengguna dalam kerja mereka. Hari ini kita akan menganalisis sebab berdasarkan kes sebenar, dan akhirnya memberikan penyelesaian optimum dalam projek React dan Vue.
Artikel ini akan menerangkan dengan jelas:
Apakah prinsip Modul CSS dalam React? :global
Apa yang dilakukannya?
Apakah prinsip Scoped dalam Vue? Apakah pemilih tindakan mendalam? (Belajar perkongsian video: tutorial video vue)
Mari kita tidak bercakap tentang konsep dahulu, dan mulakan terus dari keperluan: Saya menggunakan perpustakaan komponen Antd untuk memaparkan sebuah kalendar.
Sekarang saya mahu menukar sempadan biru di atas tarikh semasa kepada ungu.
Anda boleh mencuba untuk melihat sama ada anda boleh mencapainya.
Sama ada React atau Vue, keseluruhan Kalendar dirangkumkan Kami tidak boleh hanya menambah gaya/kelas di luar komponen untuk menukar gaya dalaman.
import { Calendar } from 'antd'; ... <div className="myWrapper"> <Calendar class="custom"/> </div>
Mula-mula gunakan alat pembangun untuk mencari gaya yang sepadan: .ant-picker-calendar-date-today
, inilah yang kita mahu untuk mengubah suai.
.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today { border-color: #1890ff; }
Mereka yang biasa dengan pek web harus tahu bahawa fail CSS yang diimport akhirnya akan diproses oleh pemuat gaya. Ringkasnya, fungsinya adalah untuk membungkus fail CSS, meletakkannya dalam tag gaya, dan akhirnya memasukkannya ke dalam HTML sebagai helaian gaya dalaman. Ini dilakukan sama ada gaya perpustakaan komponen atau gaya tersuai yang kami tulis.
Kami perlu memperkenalkan gaya perpustakaan komponen sebelum gaya tersuai, supaya gaya tersuai boleh mempunyai keutamaan yang lebih tinggi.
Menukar terus kod sumber CSS pustaka komponen ialah kaedah yang paling mudah dan kasar. Buka folder node_modules projek anda, klik padanya lapisan demi lapisan, cari fail gaya yang sepadan, dan ubah suai mengikut keperluan anda.
Memang boleh dilaksanakan untuk mengendalikan projek peribadi dengan cara ini, tetapi apabila bekerja dalam satu pasukan, lebih menyusahkan untuk menyegerakkan nod_modules tempatan orang lain, dan ia hanya boleh dikira sebagai kaedah 60 penguraian.
Seperti yang dinyatakan sebelum ini, meletakkan fail CSS anda sendiri di belakang gaya perpustakaan komponen boleh memastikan keutamaan penyesuaian yang lebih tinggi. Selagi anda menulis semula gaya dengan nama yang sama, anda secara teorinya boleh melaksanakan kumpulan ganti.
Tetapi ini? Pemprosesan akan mendapati ia tidak berfungsi:
/* 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> ...
Kerana keutamaan pemilih gabungan CSS juga terlibat.
Keutamaan asas tidak perlu dikatakan: !important>内联样式>ID选择器>类选择器>标签选择器
. (Hack seperti !important akan menyukarkan projek untuk diselenggara dan tidak disyorkan untuk digunakan)
Atas dasar ini, terdapat lima pemilih gabungan yang perlu mengumpul markah keutamaan Ambil pemilih kelas sebagai contoh:
Pemilih turunan (ruang): .A .B
memilih semua elemen .B selepas elemen .A,
pemilih elemen anak (lebih besar daripada Tanda ): .A>.B
Memilih unsur .B antara keturunan langsung unsur .A
Pemilih adik beradik bersebelahan (tanda tambah): .A .B
Memilih elemen sejurus selepas .A elemen Adik beradik pertama.B elemen
Pemilih adik beradik berikutnya (~ nombor): .A~.B
Pilih semua elemen adik.B selepas elemen A
Pemilih persimpangan (disambungkan bersama): .A.B
Pilih elemen yang mempunyai kedua-dua atribut .A dan .B
Peraturan di atas kelihatan sangat rumit , sebenarnya, yang paling praktikal ialah pemilih keturunan pertama, ingat sahaja. Pustaka komponen Antd menggunakannya:
.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today { border-color: #1890ff; }
Jika markah keutamaan pemilih kelas ialah 10 mata, maka tiga pemilih keturunan yang terbentuk ialah 30 mata.
Dan gaya tersuai? Ia hanya mempunyai 10 mata, jadi walaupun ia diperkenalkan kemudian, ia tidak boleh ditimpa dengan jayanya.
.ant-picker-calendar-date-today { border-color: purple; // 覆盖为紫色 }
Anda perlu menulis semula sepenuhnya keseluruhan pemilih untuk mencapai kesan yang diingini.
Satu lagi perkara yang perlu ditambahkan di sini ialah ia juga merupakan pemilih gabungan, tetapi keutamaan pemilih kesatuan (koma) bukanlah terkumpul:
.A, .B
Pilih elemen .A atau .B (boleh jadikan ruang koma)
上面我们引入自定义的全局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和深度作用选择器做样式覆盖。
如果这篇文章对你有帮助,给我点个赞和在看吧~
Atas ialah kandungan terperinci Bagaimana untuk mengatasi gaya perpustakaan komponen? Analisis ringkas penyelesaian untuk projek React dan Vue. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!