摘要

在单文件组件样式中支持使用组件状态驱动的 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 中声明两个响应式的属性,分别是 wallpaperBlurwallpaperMaskwallpaperBlur 表示壁纸的模糊程度, 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. NVIDIA GPU上的随机数生成

    NVIDIA GPU上的随机数生成 NVIDIA CUDA随机数生成库(cuRAND)提供高性能的GPU加速的随机数生成(RNG).cuRAND库使用NVIDIA GPU中提供的数百个处理器内核,将质 ...

  2. GPU编程和流式多处理器(七)

    6. 杂项说明 6.1. warp级原语 warp作为执行的原始单元(自然位于线程和块之间),重要性对CUDA程序员显而易见.从SM 1.x开始,NVIDIA开始添加专门针对thread的指令. Vo ...

  3. Linux架构思维导图

    Linux架构思维导图 GUI(Graphical User Interface,图形用户界面) Linux学习路径 软件框架 Linux桌面介绍 FHS:文件系统目录标准 Linux需要特别注意的目 ...

  4. 剑指 Offer 07. 重建二叉树

    链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/ 标签:树.递归 题目 输入某二叉树的前序遍历和中序遍历的结果,请重建该二 ...

  5. MySQL的启动选项和系统变量该如何配置?

    MySQL的配置信息可以通过两种方式实现,一种是命令行形式,在启动MySQL服务时后边带上相关配置参数,此种方式会在MySQL重启后失效.另外一种是通过写入配置文件,如my.cnf,启动或者重启MyS ...

  6. Hdoop

    优势:1.低成本  2.高扩展 3.成熟的生态圈 1.安装虚拟机 vi /etc/profile

  7. 日志挖掘针对DML语句

    作用: 针对用户的误操作,比如更改数据错误,误删除表等,可以用日志挖掘的方式,跟踪哪个用户什么时候做的操作,并进行数据还原. 一.前期准备: 1.添加最小补充日志,能够记录到更详细的信息,为日志挖掘分 ...

  8. 【Java】equals 和 == 的区别

    之前有在 Java字符串比较(3种方法)以及对比 C++ 时的注意项 中写过一点关于 equals()与==的比较,但最近的Java考试复习过程中发现有部分情况没涉及到,故重新学习一下 在编写代码的时 ...

  9. JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇

    JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇 作为一个使用Java语言开发的程序员,我们都知道,要想运行Java程序至少需要安装JRE(安装JDK也没问题).我们也知道我们Java程序 ...

  10. 配置中心之Nacos简介,使用及Go简单集成

    简介 为什么需要配置中心 ​ 我们现在有一个项目, 使用Gin进行开发的, 配置文件我们知道是一个config.yaml的文件, 也知道这个配置文件在项目启动时会被加载到内存中使用; 考虑三种情况: ...