Vue3下style CSS变量注入怎样实现?一文带你看懂

Admin 2021-10-21 群英技术资讯 953 次浏览

    Vue3下style CSS变量注入怎样实现?一些朋友可能对CSS变量注入的内容不是很了解,对此本文就给大家来介绍一下CSS变量注入,下文有示例及详细的介绍,感兴趣的朋友就继续往下看吧。

    摘要

    在单文件组件样式中支持使用组件状态驱动的 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://github.com/vuejs/rfcs/pull/231

    到此这篇关于Vue3 style CSS 变量注入的实现的文章就介绍到这了,更多相关Vue3 style CSS变量注入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • js与css的阻塞问题详析
    • 带你了解CSS基础知识,样式
    • JS、CSS和HTML实现注册页面
    • vue3实现CSS无限无缝滚动效果
    • React引入antd-mobile+postcss搭建移动端
    • 浅谈CSS不规则边框的生成方案
    • 详解CSS故障艺术
    • CSS3使用过度动画和缓动效果案例讲解
    群英智防CDN,智能加速解决方案
    标签: CSS变量注入

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

    猜你喜欢

    成为群英会员,开启智能安全云计算之旅

    立即注册
    专业资深工程师驻守
    7X24小时快速响应
    一站式无忧技术支持
    免费备案服务
    免费拨打  400-678-4567
    免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
    在线客服
    微信公众号
    返回顶部
    返回顶部 返回顶部
    在线客服
    在线客服