我正在参加「掘金·启航计划」,快来一起参与吧!
我正在参加「掘金·启航计划」
前言
上一章,我们已经初步实现了zwf-input
自定义组件,在这章里,我们将会讲到,如何使用CSS自定义令牌
更改组件内的样式,以及它的替代方式::part
等等相关知识点。感兴趣的同学,千万别走开哦~
表单元素
没错,我们的自定义组件zwf-input
可以像表单元素
那样使用
<label id="label">名称:</label>
<zwf-input name="leaves" aria-labelledby="label"></zwf-input>
- 添加
name
属性,类似原生的表单元素,在表单提交时,会将多个name值自动组成数组提交 - 使用
aria-labelledby="label"
和id="label"
,将zwf-input
与label
标签相关联,这样屏幕阅读器在读到aria-labelledby
会自动得知该input
的标签意思
如何外部更改自定义组件的样式
在上一章里,我们知道zwf-input
是在沙盒内部里,由于沙箱的内部独立性,那我们在外面如何更改它的内部样式呢?
CSS Custom Properties
(CSS自定义属性,即令牌token)
在zwf-input
组件内,新增如下样式代码:
static styles = css`
label,
input {
color: var(--q-primary, var(--q-amber700, #d53600));
font-family: var(--q-input-font-family, 'Boogaloo');
}
label {
font-size: var(--q-input-label-font-size, 16px);
}
input {
font-size: var(--q-input-font-size, 24px);
}
`
var
为CSS
的函数,可以用它自定义一些样式变量,它的基本语法如下所示:
var(custom-property-name, value)
- custom-property-name: 必需。自定义属性的名称,必需以 -- 开头
- value:可选。备用值,在属性不存在的时候使用。
在引入zwf-input
组件的App.vue
新增如下代码:
<template>
<zwf-input class="test" value="123" label="ceshi" aria-labelledby="label"></zwf-input>
</template>
<style>
zwf-input {
--q-primary: #d50201;
--q-input-font-family: 'Comic Sans';
--q-input-font-size: 18px;
--q-input-label-font-size: 16px;
}
</style>
网页效果运行如下所示:
非常棒,对吧?除了CSS Custom Properties
,还有哪个方法可以更改组件的内部样式呢?
::part
我们可以使用CSS
的::part()
API,来公开指定的shadow dom
元素,它的用法与slot
类似,特点如下所示:
- 暴露部分碎片,供外面更改样式
- 适用于:
一次性
的自定义样式,和少数自定义属性 - 较难维护设计的一致性原则
在zwf-input
组件内,更改的代码如下所示:
<label id="label" part="label">${this.label}</label>
添加了part="label"
属性,将label
标签暴露给外面,供其更改样式
在App.vue
新增如下样式代码:
zwf-input::part(label) {
color: red;
font-size: 2rem;
font-weight: bold;
}
网页运行效果如下所示:
如何自动切换为深色主题(dark mode)
我们可以使用@media(prefers-color-scheme: dark)
自动识别电脑的深色主题,从而实现主题样式的自动切换
如何开启win 10电脑的深色主题
在桌面,右键选择个性化
,如下图所示:
在面板内,选择深色
,如下图所示:
在zwf-input
组件内新增如下的样式代码
为了更好地体现本小节的代码效果,记住屏蔽之前的样式代码
@media(prefers-color-scheme: dark) {
:root {
--q-primary: var(--q-amber200, green);
}
}
我们之所以使用:root选择器,是因为与HTML 标签选择器相比,它不是那么具体化,这是为了防止客户覆盖我们的初始定义
页面运行效果如下图所示(为了更好地展示效果,我特意将图片做了放大化处理):
很神奇,是不是?
CSS Custom Properties
的问题
使用CSS Custom Properties
自定义样式变量,虽然很不错,但是它也存在如下的两个问题:
- 无法确定变量值的有效性(用户编写的变量值有可能是错误的)
- 在回调函数内,很难保持其初始值
如何解决上述问题呢?Registered Properties
应运而生
Registered Properties
它的代码格式如下所示:
@property --design-token {
syntax: '<color>';
inherits: true;
initialValue: 'goldenrod'
}
使用@property
自定义了一个--design-token
变量
- syntax:可以设置为许多类型,如链接、数字、URL、图像,还有颜色,使自定义属性和原生用户代理属性类似,如果用户提供的值无效,则浏览器会自动忽略它
- inherits:为true的话,则表示我们希望在父元素设置一次之后,所有的子元素都能继承它;若为false,则表示我们不希望用户改变该令牌的值,所以浏览器无需额外计算该继承关系(
浏览器性能将得到提升
)
在zwf-input
组件内,更改的代码如下所示:
static styles = css`
@property --q-amber700 {
syntax: '<color>',
inherits: false,
initial-value: '#d53600'
}
@property --q-primary {
syntax: '<color>',
inherits: true
}
:root {
--q-primary: var(--q-amber700);
}
@property --q-amber200 {
syntax: '<color>',
inherits: false,
initial-value: '#ff8503'
}
@media(prefers-color-scheme: dark) {
:root {
--q-primary: var(--q-amber200);
}
}
label,
input {
color: var(--q-primary);
font-family: var(--q-input-font-family);
}
label {
font-size: var(--q-input-label-font-size);
}
input {
font-size: var(--q-input-font-size);
}
slot[name="icon"]::slotted(*) {
display: none;
}
slot[name="icon"]::slotted(svg) {
display: inline-flex;
width: 36px;
height: 36px;
}
`
结构与之前的相比,是不是清晰了很多?
App.vue
内部的样式代码不变,如下所示:
zwf-input {
--q-primary: #d50201;
--q-input-font-family: 'Comic Sans';
--q-input-font-size: 18px;
--q-input-label-font-size: 16px;
}
页面运行效果如下所示:
尾声
在本节课内,我们学习了CSS custom properties
、::part
等知识点,如果大家对该系列文章感兴趣的话,可以私聊我,或关注我,和大家一起学习进步,一直是件令人高兴的事~~~
感谢大家的关注,欢迎在评论区留言