Vue3 中的 CSS 语法糖

344 阅读2分钟
  • v-bind()
  • :deep()
  • :slotted()
  • :global()
  • module

v-bind()

当在 <style> 中使用 v-bind() 时,会将 <script> 中的值通过 css 变量的方式绑定在父元素上,并给他们编上序号

<script setup>
  const boxHeight = ref('200px');
</script>

<style>
.box {
  height: v-bind(boxHeight);
}
</style>

编译结果

<div class="box" --fac4af80-boxHeight: 200px;>

注意事项

  1. 当需要使用带单位的 css 属性值时,需要提前在 <script> 中拼接好后续的单位,v-bind() 函数中不支持拼接

    <style>
      .wrapper {
        height: v-bind(boxHeight + 'px'); // ❌ 这将导致在页面中无法正常使用
      }
    </style>
    

    处理措施:需要提前拼接

    <script>
      const boxHeight = computed(() => 200 + 'px');
    </script>
    
  2. 如果使用的是某个对象中的值,打点的操作需要使用引号包裹

    <script setup>
      const obj = reactive({
        width: '200px',
        height: '300px'
      })
    </script>
    
    <style>
      .wrapper {
        height: v-bind('obj.width');
      }
    </style>
    
  3. 如果需要使用的是字符串,就需要使用 JSON.stringify() 将其进行转换,(String()toString() 函数无法实现,因为在 JS 中本就是 String 类型)不然 css 给设置的变量在 css 也会是一个变量

    <script>
      const nextText = computed(() => {
        return JSON.stringify(nextNavLink.value.text); // 前提是该结果输出的是一个字符串类型
      });
    </script>
    

    这样在父元素中的变量值是带引号的

    --fac4af80-nextText: "闭包";

    错误示范

    <script>
      const nextText = computed(() => {
        return nextNavLink.value.text;
      });
    </script>
    

    这样在父元素中的变量值是不带引号的,在使用时,默认会当作 css 中的变量去使用,而不是字符串

    --fac4af80-nextText: 闭包;

  4. 使用表达式时需要用引号包裹,如果不为表达式则不用使用引号包裹

    <script setup>
      const color = ref('red');
    </script>
    
    <style>
    .red {
      color: v-bind(color.value);
    }
    </style>
    

:deep()

在标记了 scoped 的样式表中,可以使用 :deep() 伪类选择器做更深度的选择

<style scoped>
  .wrapper :deep(.box) {
    color: red;
  }
</style>

:slotted()

在默认情况下,作用域样式不会影响到 <slot/> 渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。可以使用 :slotted() 伪类以明确地将插槽内容作为选择器的目标

<style scoped>
.wrapper :slotted(.box) {
  color: red;
}
</style>

:global()

如果想让其中一个样式规则应用到全局,比起另外创建一个 <style>,可以使用 :global() 来实现

<style scoped>
  :global(.red) {
    color: red;
  }
</style>

Css Modules

一个 <style module> 标签会被编译为 CSS Modules 并且将生成的 CSS class 作为 $style 对象暴露给组件:

<template>
  <p :class="$style.red">This should be red</p>
</template>

<style module>
.red {
  color: red;
}
</style>

亦可自定义属性名

<template>
  <p :class="classes.red">red</p>
</template>

<style module="classes">
.red {
  color: red;
}
</style>