摘要

在单文件组件样式中支持使用组件状态驱动的 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. TVM自动调度器

    TVM自动调度器 随着模型大小,算子多样性和硬件异构性的不断增长,优化深度神经网络的执行速度非常困难.从计算的角度来看,深度神经网络只是张量计算的一层又一层.这些张量计算(例如matmul和conv2 ...

  2. Java设计模式(3:接口隔离原则和迪米特法则详解)

    一.接口隔离原则 使用多个接口,而不使用单一的接口,客户端不应该依赖它不需要的接口.尽量的细化接口的职责,降低类的耦合度. 我们先来看一个例子: 小明家附近新开了一家动物园,里面有老虎.鸟儿.长颈鹿. ...

  3. java面试必知必会——排序

    二.排序 时间复杂度分析 排序算法 平均时间复杂度 最好 最坏 空间复杂度 稳定性 冒泡 O(n²) O(n) O(n²) O(1) 稳定 选择 O(n²) O(n²) O(n²) O(1) 不稳定 ...

  4. 在模仿中精进数据分析与可视化01——颗粒物浓度时空变化趋势(Mann–Kendall Test)

      本文是在模仿中精进数据分析与可视化系列的第一期--颗粒物浓度时空变化趋势(Mann–Kendall Test),主要目的是参考其他作品模仿学习进而提高数据分析与可视化的能力,如果有问题和建议,欢迎 ...

  5. 【NX二次开发】Block UI 表达式

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

  6. NX二次开发-曲线或边分析函数

    UF_EVAL_is_arc   判断是圆形曲线或边UF_EVAL_ask_arc 圆形曲线或边分析,得到曲线或边的信息 类似的函数还有以下这些: UF_EVAL_is_ellipse // 椭圆UF ...

  7. 【NX二次开发】缝合片体例子UF_MODL_create_sew

    缝合片体,没有成功缝合的片体涂绿色. 效果:  源码: extern DllExport void ufusr(char *param, int *returnCode, int rlen) { UF ...

  8. 【Azure 机器人】微软Azure Bot 编辑器系列(6) : 添加LUIS,理解自然语言 (The Bot Framework Composer tutorials)

    欢迎来到微软机器人编辑器使用教程,从这里开始,创建一个简单的机器人. 在该系列文章中,每一篇都将通过添加更多的功能来构建机器人.当完成教程中的全部内容后,你将成功的创建一个天气机器人(Weather ...

  9. 消失之物(背包DP)(容斥或分治)

    容斥做法: 首先n^2搞出f[i][j]第i个物品,j体积的方案数. 去除每个物品贡献: 设个g[i][j]表示当i不选,j体积方案数(注意不是此时的范围相对于全局,而不是1---i) 那么我们用到一 ...

  10. Windows内核开发-Windows内部概述-1-

    Windows内部概述-1- 进程: 进程是一个程序的运行实例的控制和管理对象.一般的程序员所说进程运行,这样的说法是不对的,因为进程不能运行程序,进程只能管理该程序运行.线程才是真正的执行代码的东西 ...