作者: 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的主旨是创建通用, 灵活,稳定的组件。准备好了吗?出发喽!
先看一个简单的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>
我们希望一个组件越通用越好,这样我们就可以在不同的网站重用它了。但是如何编写一个这样的组件呢?
首先,我们假设不只是需要一段文本内容。如果我们想要不同的内容,例如e <strong></strong> 或者一个icon?最好的解决办法是实用slots。
让我们继续刚才的话题,通常,我们的经验是使用 scoped ,在不同的组件中定义CSS。但是,如果我们需要一些全局的配置CSS呢?这样我们就违反了DRY规则。如果我们需要改变主色,我们不得不改变任何一个硬编码的地方。那么解决方案是神马呢?实用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>
我们会在另外一个文件中自定义 :root 选择器,但是为了清楚起见,我们现在当前组件的文件中定义。
颜色和间距在web设计中经常改变的内容,我们需要保证不因他们的改变而改变。
通过改变属性来影响所有的组件从而来达到重用的目的,会使得我们的组件非常灵活。
那么,如果定义一个网站主题呢?我们可以实用免声明的自定义属性。先解释一下:
<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这些变量呢?这就是技巧了,我们没有定义。
我们实用了一个为定义的自定义属性但是给它了一个默认值。所以,如果运行时,任何一个属性没有被定义的话,它就会回溯到它的默认值。
这意味着,我们可以从外面定义这些属性。
<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>
这样非常灵活,但可能太灵活了。我们不想暴露太多细节给使用者。这个使用者可能想要自己设定一个主色来代替原来的创建一个新的主题。但是这个Button需要知道,它被设置了什么参数。所以让我们来自定义属性和主题。
<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这两个来达到创建新主题的目的。
以上就是全部内容了。感谢你读完了全部内容。点击 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.