Vue3 style CSS 变量注入

更新日期: 2021-07-21阅读量: 695标签: Vue3

摘要

在单文件组件样式中支持使用组件状态驱动的 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 编译器将执行以下操作:

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

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

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

相应的变量将作为内联样式被注入到组件的根元素中。对于上面的例子,最终渲染的 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 变量更新影响。

来自:https://www.cnblogs.com/guangzan/archive/2021/07/21/15022091.html


链接: https://www.fly63.com/article/detial/10551

vue3.x 新特性 - CompositionAPI

安装 vue-cli3,在使用任何 @vue/composition-api 提供的能力前,必须先通过 Vue.use() 进行安装,安装插件后,您就可以使用新的 Composition API 来开发组件了。

Vue3数据响应系统

Vue3 就是基于 Proxy 对其数据响应系统进行了重写,现在这部分可以作为独立的模块配合其他框架使用。数据响应可分为三个阶段: 初始化阶段 --> 依赖收集阶段 --> 数据响应阶段

快速进阶Vue3.0

在2019.10.5日发布了Vue3.0预览版源码,但是预计最早需要等到 2020 年第一季度才有可能发布 3.0 正式版。新版Vue 3.0计划并已实现的主要架构改进和新功能:

Vue 3 对 Web 应用性能的改进

有关即将发布的 Vue.js 的第 3 个主要版本的信息越来越多。通过下面的讨论,虽然还不能完全确定其所有内容,但是我们可以放心地认为,它将是对当前版本(已经非常出色)的巨大改进。 Vue 团队在改进框架 API 方面做得非常出色

Vue3 中令人兴奋的新功能

用新的 Vue 3 编写的程序效果会很好,但性能并不是最重要的部分。对开发人员而言,最重要的是新版本将会怎样影响我们编写代码的方式。如你所料,Vue 3 带来了许多令人兴奋的新功能。值得庆幸的是

200 行从零实现 vue3

emmm 用半天时间捋顺了 vue3 的源码,再用半天时间写了个 mini 版……我觉得我也是没谁了,vue3 的源码未来一定会烂大街的,我们越早的去复现它,就……emm可以越早的装逼hhh

从 Proxy 到 Vue 源码,深入理解 Vue 3.0 响应系统

10 月 5 日,尤雨溪在 GitHub 开放了 Vue 3.0 处于 pre-alpha 状态的源码,这次 Vue 3.0 Updates 版本的更新,将带来五项重大改进:速度体积、可维护性、面向原生、易用性

Vue 的数据响应式(Vue2 及 Vue3)

从一开始使用 Vue 时,对于之前的 jq 开发而言,一个很大的区别就是基本不用手动操作 dom,data 中声明的数据状态改变后会自动重新渲染相关的 dom。换句话说就是 Vue 自己知道哪个数据状态发生了变化及哪里有用到这个数据需要随之修改。

在Vue2与Vue3中构建相同的组件

Vue 开发团队终于在今天发布了 3.0-beta.1 版本,也就是测试版。通常来说,从测试版到正式版,只会修复 bug,不会引入新功能,或者删改老功能。所以,如果你对新版本非常感兴趣,或者有新项目即将上马,不妨尝试一下新版本

Vue3中的Vue Router初探

对于大多数单页应用程序而言,管理路由是一项必不可少的功能。随着新版本的Vue Router处于Alpha阶段,我们已经可以开始查看下一个版本的Vue中它是如何工作的。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!