作者: Cesar Alberca (@cesalberca), a frontend developer at Autentia that have worked with Vue professionally for 2 years and counting. He’s also done projects in React and Angular and he’s passionate about good practices and testing.
I met Cesar at the last Codemotion Madrid conference and I have to say he’s a really cool guy with lots of potential! Don’t expect too little from this tip ??.
正文開始
大家好哇!VueDoes的主旨是創(chuàng)建通用, 靈活,穩(wěn)定的組件。準(zhǔn)備好了嗎?出發(fā)嘍!
先看一個(gè)簡單的button
<template>
<button><slot/></button>
</template>
<script>
export default {
name: "AppButton",
};
</script>
<style scoped>
button {
border: 4px solid #41b883;
padding: 12px 24px;
transition: 0.25s ease-in-out all;
}
button:hover {
color: white;
background-color: #41b883;
}
</style>
我們希望一個(gè)組件越通用越好,這樣我們就可以在不同的網(wǎng)站重用它了。但是如何編寫一個(gè)這樣的組件呢?
首先,我們假設(shè)不只是需要一段文本內(nèi)容。如果我們想要不同的內(nèi)容,例如e <strong></strong> 或者一個(gè)icon?最好的解決辦法是實(shí)用slots。
讓我們繼續(xù)剛才的話題,通常,我們的經(jīng)驗(yàn)是使用 scoped ,在不同的組件中定義CSS。但是,如果我們需要一些全局的配置CSS呢?這樣我們就違反了DRY規(guī)則。如果我們需要改變主色,我們不得不改變?nèi)魏我粋€(gè)硬編碼的地方。那么解決方案是神馬呢?實(shí)用custom properties 。
<style scoped>
:root {
--primary-color: #41b883;
--on-primary-color: white;
--small-spacing: 12px;
--normal-spacing: calc(var(--small-spacing) * 2);
}
button {
border: 4px solid var(--primary-color);
padding: var(--small-spacing) var(--normal-spacing);
transition: 0.25s ease-in-out all;
}
button:hover {
color: var(--on-primary-color);
background-color: var(--primary-color);
}
</style>
我們會(huì)在另外一個(gè)文件中自定義 :root 選擇器,但是為了清楚起見,我們現(xiàn)在當(dāng)前組件的文件中定義。
顏色和間距在web設(shè)計(jì)中經(jīng)常改變的內(nèi)容,我們需要保證不因他們的改變而改變。
通過改變屬性來影響所有的組件從而來達(dá)到重用的目的,會(huì)使得我們的組件非常靈活。
那么,如果定義一個(gè)網(wǎng)站主題呢?我們可以實(shí)用免聲明的自定義屬性。先解釋一下:
<style scoped>
button {
border: 4px solid var(--button-border-color, var(--primary-color));
padding: var(--small-spacing) var(--normal-spacing);
transition: 0.25s ease-in-out all;
}
button:hover {
color: var(--button-hover-text-color, var(--on-primary-color));
background-color: var(--button-hover-background-color, var(--primary-color));
}
</style>
我們在哪里定義--button-border-color, --button-hover-text-color and --button-hover-background-color這些變量呢?這就是技巧了,我們沒有定義。
我們實(shí)用了一個(gè)為定義的自定義屬性但是給它了一個(gè)默認(rèn)值。所以,如果運(yùn)行時(shí),任何一個(gè)屬性沒有被定義的話,它就會(huì)回溯到它的默認(rèn)值。
這意味著,我們可以從外面定義這些屬性。
<template>
<AppButton class="custom-theme">Hello VueDose!</AppButton>
</template>
<style scoped>
.custom-theme {
--button-border-color: pink;
--button-hover-background-color: rgb(206, 161, 195);
}
</style>
這樣非常靈活,但可能太靈活了。我們不想暴露太多細(xì)節(jié)給使用者。這個(gè)使用者可能想要自己設(shè)定一個(gè)主色來代替原來的創(chuàng)建一個(gè)新的主題。但是這個(gè)Button需要知道,它被設(shè)置了什么參數(shù)。所以讓我們來自定義屬性和主題。
<template>
<button :style="getTheme"><slot/></button>
</template>
<script>
export default {
name: "AppButton6",
props: {
theme: String,
validator: (theme) => ['primary', 'secondary'].includes(theme)
},
computed: {
getTheme() {
const createButtonTheme = ({
borderColor,
hoverTextColor,
hoverBackgroundColor
}) => ({
'--button-border-color': borderColor,
'--button-hover-text-color': hoverTextColor,
'--button-hover-background-color': hoverBackgroundColor
})
const primary = createButtonTheme({
borderColor: 'var(--primary-color)',
hoverTextColor: 'var(--on-primary-color)',
hoverBackgroundColor: 'var(--primary-color)'
})
const secondary = createButtonTheme({
borderColor: 'var(--secondary-color)',
hoverTextColor: 'var(--on-secondary-color)',
hoverBackgroundColor: 'var(--secondary-color)'
})
const themes = {
primary,
secondary
}
return themes[this.theme]
}
}
};
</script>
So we can do this easily:
<AppButton theme="secondary">Hello VueDose!</AppButton>
And finally. All the cool kids nowadays are doing dark themes right?
<template>
<main class="wrapper" :class="mode">
<AppButton @click.native="toggleTheme" theme="secondary">
Click me to change to dark mode!
</AppButton>
</main>
</template>
<script>
import AppButton from "./components/AppButton";
export default {
name: "App",
data: () => ({
mode: 'light'
}),
components: {
AppButton
},
methods: {
toggleTheme() {
this.mode = this.mode === 'light' ? 'dark' : 'light'
}
}
};
</script>
<style scoped>
.light {
--background-color: white;
--on-background-color: #222;
}
.dark {
--background-color: #222;
--on-background-color: white;
}
.wrapper {
transition: 1s ease-in-out background-color;
background-color: var(--background-color);
color: var(--on-background-color);
}
</style>
我們可以切換 --background-color 和 --on-background-color這兩個(gè)來達(dá)到創(chuàng)建新主題的目的。
以上就是全部內(nèi)容了。感謝你讀完了全部內(nèi)容。點(diǎn)擊 this CodeSandbox!
Here it goes today’s tip!
Remember you can read this tip online (with copy/pasteable code), and don’t forget to share VueDose with your colleagues, so they also know about these tips as well!
See you soon.