如何利用css var函數(shù)讓你的組件樣式輸出規(guī)范樣式API可定制性更高
我們平時(shí)在使用Elementui Antdesing這些UI庫(kù)時(shí),難免會(huì)碰到使用deep強(qiáng)行侵入式去修改組件內(nèi)部樣式的情況;比如下列代碼,我們需要把a(bǔ)nt的分頁(yè)樣式進(jìn)行高度自定義,就得使用deep去修改;

這種實(shí)現(xiàn)方式確實(shí)能夠達(dá)到我們的目的,但在開發(fā)時(shí)確總覺得不太合適:
1、他屬于強(qiáng)行入侵組件內(nèi)部去修改,雖然不會(huì)有大問(wèn)題,但總覺得這種取巧方式有點(diǎn)不可取。
2、每次寫deep時(shí)需要手動(dòng)檢查DOM元素進(jìn)行編輯,UI文檔中并不會(huì)有相關(guān)API文檔;
為了解決心中的這兩個(gè)結(jié)癥,趁最近寫組件的機(jī)會(huì)探索了下CSS 的var函數(shù),發(fā)現(xiàn)他可以很好的解決以上問(wèn)題。
利用var函數(shù)我們可以具體解決組件開發(fā)的以下問(wèn)題:
1、組件樣式自定義可以更加個(gè)性化
2、現(xiàn)在很多組件庫(kù)實(shí)現(xiàn)一些樣式控制還是依靠props傳參的形式,這種var函數(shù)結(jié)合Style可完全避免props傳參的情況,把樣式跟props區(qū)分開;
3、在組件文檔中可明確定制樣式屬性API;使組件樣式可以跟Props屬性一樣以傳參概念去進(jìn)行高度定制,在使用組件樣式時(shí)不需要像使用deep一樣打開f12去一層一層的找
4、不會(huì)侵入式的改動(dòng)組件內(nèi)部樣式
5、這個(gè)方案與deep互不排斥,如果開放的樣式API不夠用還是可以繼續(xù)使用deep;
看下面需求,是如何利用css var函數(shù)實(shí)現(xiàn)一個(gè)可自定義大小,顏色,以及子元素樣式的卡片

上代碼
//Card.vue
<template>
<div class="card">
<img class="card-img" :src="img" />
<p class="card-desc">{{ desc }}</p>
</div>
</template>
<style lang="scss" scoped>
.card {
// 這些以"--"開頭的變量就是我們開放可自定義的樣式屬性了,可以在組件使用文檔中明確開放
//卡片根元素樣式
--width: 150px;
--height: auto;
--border-size: 1px;
--border-color: #ccc;
--border-radius: 5px;
--bg: #eee;
// 圖片可定樣式
--img-width: 130px;
--img-height: 130px;
--img-radius: 50%;
// 卡片描述樣式
--desc-size: 16px;
--desc-line-height: 32px;
--desc-color: #333;
height: var(--height);
width: var(--width);
border: var(--border-size) solid var(--border-color);
border-radius: var(--border-radius);
background: var(--bg);
padding: 10px;
&-img {
width: var(--img-width);
height: var(--img-height);
border-radius: var(--img-radius);
overflow: hidden;
}
&-desc {
font-size: var(--desc-size);
color: var(--desc-color);
line-height: var(--desc-line-height);
text-align: center;
}
}
</style>
這時(shí)候我們?cè)贏PI文檔則可明確規(guī)定樣式定制屬性了:

組件使用方式:
//demo.vue
<template>
<div >
<Card desc="我是默認(rèn)的樣式我是默認(rèn)的樣式我是默認(rèn)的樣式" :img="img" />
<Card class="card_1" desc="自定義樣式,子元素圖片變小了" :img="img" />
<Card class="card_2" desc="自定義樣式,圓角沒(méi)了,描述字變小了,高度高了" :img="img" />
</div>
</template>
<script>...</script>
<style lang="scss" scoped>
.card_1 {
--width: 100px;
--height: 200px;
--border-radius: 20px;
--img-width: 80px;
--img-height: 50px;
--img-radius: 10px;
--desc-color: #f00;
--desc-size: 12px;
--desc-line-height: 21px;
}
.card_2 {
--height: 300px;
--border-radius: 0px;
--bg: #fff;
--img-radius: 50px;
--desc-size: 14px;
--desc-line-height: 21px;
}
</style>
以上就是一個(gè)基本的組件實(shí)現(xiàn);還種情況我們?cè)谑褂肬I庫(kù)時(shí)也會(huì)碰到需要使用Props傳過(guò)來(lái)計(jì)算的參數(shù),比如下列代碼:

這種我們也可以把這些全提出來(lái)使用style屬性。讓樣式與js參數(shù)徹底隔離
//demo.vue
<template>
<card
desc="我是默認(rèn)的樣式我是默認(rèn)的樣式"
:img="img"
:style="hoverStyle"
@mouseout="hoverStyle = {}"
@mouseover="handleHover"
/>
</template>
<script setup>
let hoverStyle = ref({});
const handleHover = () => {
hoverStyle.value = { '--bg': '#f0f', '--width': '180px' };
};
</script>
我們?cè)诮M件內(nèi)
JS可以使用props.style獲取到設(shè)置的值,css中可以使用calc變量與var結(jié)合去計(jì)算你想要的值
//card.vue
<template>
<div class="card" :style="style">
{{ width }}
<img class="card-img" :src="img" />
<p class="card-desc">{{ desc }}</p>
</div>
</template>
<script setup>
const $props = defineProps({
img: {
type: String,
default: '',
},
desc: {
type: String,
default: '',
},
style: {
type: Object,
default: () => ({}),
},
});
//假如你在js中需要用到寬度
let width = computed(() => {
return parseInt($props.style['--width'] || 150);
});
</script>
<style lang="scss" scoped>
.card{
...
//假如你有個(gè)子級(jí)元素需要基于寬度計(jì)算
.item{
width: calc(var(--width) - 100)
}
...
}
</style>
但是這種實(shí)現(xiàn)有命名空間的問(wèn)題所以需要稍微注意下變量命名,最好加獨(dú)有的命名規(guī)則。防止變量覆蓋;
//比如這樣
.ch-card{
--ch-card-width:100px;
--ch-card-height:100px;
}
總結(jié)下這種方案的優(yōu)缺點(diǎn):
優(yōu)點(diǎn)
1、組件樣式自定義可以更加個(gè)性化
2、現(xiàn)在很多組件庫(kù)實(shí)現(xiàn)一些樣式控制還是依靠props傳參的形式,這種var函數(shù)結(jié)合Style可完全避免props傳參的情況,把樣式跟props區(qū)分開;
3、在組件文檔中可明確定制樣式屬性API;使組件樣式可以跟Props屬性一樣以傳參概念去進(jìn)行高度定制,在使用組件樣式時(shí)不需要像使用deep一樣打開f12去一層一層的找
4、不會(huì)侵入式的改動(dòng)組件內(nèi)部樣式
5、這個(gè)方案與deep互不排斥,如果開放的樣式API不夠用還是可以繼續(xù)使用deep;
缺點(diǎn):
1、開發(fā)組件時(shí)會(huì)工作量會(huì)增大,但是磨刀不誤砍柴功
2、命名空間問(wèn)題導(dǎo)致命名會(huì)有點(diǎn)長(zhǎng)。
到此這篇關(guān)于如何利用css var函數(shù)讓你的組件樣式輸出規(guī)范樣式API可定制性更高的文章就介紹到這了,更多相關(guān)css var函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
- 當(dāng)Web項(xiàng)目變得越來(lái)越大時(shí),他的CSS會(huì)變得像天文數(shù)字那么大而且還變得混亂。為了幫助我們解決這個(gè)問(wèn)題,新的CSS變量很快就會(huì)出現(xiàn)在主流瀏覽器中,這篇文章主要介紹了你真的2019-01-15

