摘要

在单文件组件样式中支持使用组件状态驱动的 CSS 变量( CSS 自定义属性)。

基础示例

<template>
<div class="text">hello</div>
</template> <script>
export default {
data() {
return {
color: 'red',
font: {
size: '2em',
},
}
},
}
</script> <style>
.text {
color: v-bind (color); /* expressions (wrap in quotes) */
font-size: v-bind ('font.size');
}
</style>

动机

Vue SFC 样式提供了直接的 CSS 搭配和封装,但它是纯粹的静态的 —— 这意味着到目前为止,我们没有能力在运行时根据组件的状态动态更新样式。

现在,随着大多数现代浏览器支持原生 CSS 变量,我们可以利用它来轻松连接组件的状态和样式。

设计细节

SFC 中的标签现在支持一个自定义 CSS 函数 v-bind:

<!-- in Vue SFC -->
<style>
.text {
color: v-bind (color);
}
</style>

正如预期的那样,这将把声明的值绑定到组件状态的属性上,reactively.color color

该函数内部可以支持任意的 JavaScript 表达式,但由于 JavaScript 表达式可能包含在 CSS 标识符中无效的字符,因此在大多数情况下需要用引号来包裹它们:v-bind

.text {
font-size: v-bind ('theme.font.size');
}

当检测到这种 CSS 变量时,SFC 编译器将执行以下操作:

  1. 重写到一个带有哈希变量名称的本机。上面的内容将被改写为:v-bind () var ()

    .text {
    color: var (--6b53742-color);
    font-size: var (--6b53742-theme_font_size);
    }

    请注意,hash 将应用于所有情况,无论标签是否有范围。这意味着注入的 CSS 变量不会意外地泄漏到子组件中。

  2. 相应的变量将作为内联样式被注入到组件的根元素中。对于上面的例子,最终渲染的 DOM 将看起来像这样:

    <div style="--6b53742-color:red;--6b53742-theme_font_size:2em;" class="text">
    hello
    </div>

    注入是响应式的 ——所以如果组件的属性发生变化,注入的 CSS 变量将被相应地更新。这种更新是独立于组件的模板更新的,所以对一个纯 CSS 的响应式属性的改变不会触发模板的重新渲染。

编译细节

  • 为了注入 CSS 变量,编译器需要生成并注入如下代码到组件的 setup ()

    import { useCssVars } from 'vue'
    
    export default {
    setup() {
    //...
    useCssVars(_ctx => ({
    color: _ctx.color,
    theme_font_size: _ctx.theme.font.size,
    }))
    },
    }

    ... 这里,运行时帮助器设置了一个将变量响应性地应用到 DOM.useCssVars watchEffect 上。

  • 该编译策略要求脚本编译时首先对标签内容进行简单的重码解析,以确定要暴露的变量列表。然而,这个解析阶段不会像基于 AST 的完整解析 <style> 那样耗费开销。

  • 在生产中,变量名可以被进一步 hash,以减少 CSS 的占用。

    .text {
    color: var (--x3b2fs2);
    font-size: var (--29fh29g);
    }

    相应的生成的 JavaScript 代码将相应地使用相同的哈希值。

采用策略

这是一个完全向后兼容的新功能。然而,我们应该明确指出,它依赖于本地的 CSS 变量,所以用户需要了解浏览器的支持范围。

实践

在 script 中声明两个响应式的属性,分别是 wallpaperBlur 和 wallpaperMask。wallpaperBlur 表示壁纸的模糊程度, wallpaperMask 表示遮罩的透明度。通过 v-bind 将它们应用到 style,这意味着当我们在 script 中改变这两个值时,样式会响应更改。

// script
const wallpaperBlur = ref('0px')
const wallpaperMask = ref('rgba(0, 0, 0, 0)')
// style
.wallpaper {
filter: blur(v-bind(wallpaperBlur));
bottom: calc(v-bind(wallpaperBlur) * -2);
left: calc(v-bind(wallpaperBlur) * -2);
right: calc(v-bind(wallpaperBlur) * -2);
top: calc(v-bind(wallpaperBlur) * -2);
.wallpaper-image {
transition: background-image 0.6s, background-color 0.4s;
}
.wallpaper-mask {
background-color: v-bind(wallpaperMask);
}
}

提示

绑定恰当的属性

在上面的例子中,你可能想到到更改遮罩的透明度仅需要声明一个 0-1 的数字,之后在 style 中这样写:

.wallpaper-mask {
background-color: rgba(0, 0, 0, v-bind(wallpaperMask));
}

上文已经提到在编译阶段会将 style 中的 v-bind 改写为 CSS 变量的形式,上面的代码会被改写为这样:

.wallpaper-mask {
background-color: rgba(0, 0, 0, var (--[hash]-wallpaper_mask));
}

rgba(0, 0, 0, var (--[hash]-wallpaper_mask)) 在 CSS 中是无法被解析的。所以这就是为什么将 wallpaperMask 的初始值声明为 rgba(0, 0, 0, 0) 的原因,这是需要十分注意的一点,CSS 中还有许多类似的情况。

注意 style 的更新

在设计细节中提到相应的变量将作为内联样式被注入到组件的根元素中。最终渲染的 DOM 将看起来像这样:

<div style="--6b53742-color:red;--6b53742-theme_font_size:2em;"></div>

当你在 <script> 中改变 <style> 中绑定的属性时,内敛样式中的 CSS 变量将会响应更改。但是,并不能单独更新内敛样式其中的一个 CSS 变量,这意味着更新一个组件中的任意一个“动态样式”,都将引起根组件中的内敛样式全部更新。当 style 属性的值包含大量 CSS 变量时,你需要考虑重新组织组件。因为编译生成的 CSS 变量都将作为内联样式被注入到组件的根元素中,我们无法控制这种行为,将一个引起更新的 CSS 变量和其他 CSS 变量解耦。

试想这种情况, style 中编译生成的 CSS 变量中包含一个其值为庞大的 base64 的 CSS 变量。当更新该组件中其他 CSS 变量时,整个 style 都将更新,这将带来额外的硬件开销。我们需要将这个生成 base64 CSS 变量的组件单独抽离,以使该 CSS 变量注入到该组件的根元素,不收其他 CSS 变量更新影响。

参考资料

SFC style CSS variable injection的更多相关文章

  1. 引人瞩目的 CSS 变量(CSS Variable)

    这是一个令人激动的革新. CSS 变量,顾名思义,也就是由网页的作者或用户定义的实体,用来指定文档中的特定变量. 更准确的说法,应该称之为 CSS 自定义属性 ,不过下文为了好理解都称之为 CSS 变 ...

  2. Node聊天程序实例05:index.html和style.css

    作者:vousiu 出处:http://www.cnblogs.com/vousiu 本实例参考自Mike Cantelon等人的<Node.js in Action>一书. index. ...

  3. 可否控制<link type=text/css rel=stylesheet href=style.css>

    本篇文章主要介绍了"可否控制<link type=text/css rel=stylesheet href=style.css> ", 主要涉及到可否控制<lin ...

  4. WordPress主题开发:style.css主题信息标记

    在最简单的情况下,一个WordPress主题由两个文件构成: index.php ------------------主模版 style.css -------------------主样式表 而且s ...

  5. 跨平台移动开发 Xuijs超轻量级的框架Style CSS属性用法

    PhoneGap里面推荐使用的超轻量级的框架 Style CSS属性用法 设置css属性:setstyle 通过ID设置css属性 x$('#top1').setStyle('color', '#DB ...

  6. CSS变量(CSS variable)

    使用 CSS 变量编写你的样式代码 基本使用: 1. --variable: <declaration-value> 2. <css-attribute>: var(--var ...

  7. wordpress后台编辑如何显示定义的`style.css`样式

    wordpress后台编辑如何显示定义的style.css样式 由于公司官网采用wordpress进行搭建,但是却又自己设计页面,无奈主题只能自行构建了,直接修改wordpress自带的主题进行修改. ...

  8. [Coding Style] CSS coding style

    CSS coding style Note 结合实际工作中的规范和推荐大家使用的CSS书写规范.顺序这篇文章整合而成 Navigation CSS 书写顺序 CSS 常用文件命名 CSS 常用命名规范 ...

  9. [TypeStyle] Style CSS pseudo elements with TypeStyle

    Just like pseudo-classes, pseudo-elements are added to selectors but instead of describing a special ...

随机推荐

  1. 用TVM在硬件平台上部署深度学习工作负载的端到端 IR 堆栈

    用TVM在硬件平台上部署深度学习工作负载的端到端 IR 堆栈 深度学习已变得无处不在,不可或缺.这场革命的一部分是由可扩展的深度学习系统推动的,如滕索弗洛.MXNet.咖啡和皮托奇.大多数现有系统针对 ...

  2. BAD SLAM:捆绑束调整直接RGB-D SLAM

    BAD SLAM:捆绑束调整直接RGB-D SLAM BAD SLAM: Bundle Adjusted Direct RGB-D SLAM 论文地址: http://openaccess.thecv ...

  3. BEP 7:CUDA外部内存管理插件(上)

    BEP 7:CUDA外部内存管理插件(上) 背景和目标 在CUDA阵列接口使得能够共享不同的Python之间的数据库的访问CUDA设备.但是,每个库都与其它库区别对待.例如: Numba在内部管理内存 ...

  4. HAL库|神器cubemx的正确打开方式

    前言 工欲善其事,必先利其器.HAL库的开发不一定必须使用cubemx,但是使用了cubemx,你绝对不会后悔.基于一些小伙伴对cubemx的使用还有一些疑问,本次小飞哥从新建工程到生成工程,编写应用 ...

  5. 又见 xcrun: error: invalid active developer path 错误

    每次升级完macOS都会被 Xcode command line tools missing xcrun 问候一遍,也是挺烦的. 这个春节过光顾着吃喝玩乐,过的蛮颓废的,感觉再也追不上朋友圈各位大佬了 ...

  6. 【NX二次开发】Block UI 指定点

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  7. 【NX二次开发】镜像对象

    使用uf5946获取镜像矩阵注意:uf5946镜像这个函数,只能用#define UF_plane_type=46这种类型的数据作为镜像面,不能用#define UF_datum_plane_type ...

  8. 在centos上安装docker

    安装docker 卸载旧版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docke ...

  9. python用random模块模拟抽奖逻辑(print修改end参数使打印结果不分行)

    import random   #引入random模块,运用random函数list_one=["10081","10082","10083" ...

  10. 关于使用Draw.io画数据库E-R图的说明

    背景简介 E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型.属性和联系的方法,用来描述现实世界的概念模型. diagrams.net是用于构建图表 ...