TAY
笔记 · · 阅读 35

vue3 中 style新增了哪些特性

Vue3新增style新特性主要有引入了变量和函数,也就是状态驱动的动态css;插槽选择器;自定义注入名称等,其主要的作用就是使css更加地灵活且模板复用性更强。

一、局部样式scoped属性

当 style 标签带有 scoped 属性的时候,它的 CSS 只会应用到当前组件的元素上,其他组件不会受此样式的影响。

<style scoped>
  .example {
    color: red;
  }
</style>

<template>
  <div class="example">hi</div>
</template>

转换为:

<style>
  .example[data-v-f3f3eg9] {
    color: red;
  }
</style>

<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>

在带有 scoped 的时候,父组件的样式将不会泄露到子组件当中。不过,子组件的根节点会同时被父组件的作用域样式和子组件的作用域样式影响。这是有意为之的,这样父组件就可以设置子组件根节点的样式,以达到调整布局的目的。

二、深度选择器

在带有 scoped 的时候,它的 CSS 只会应用到当前组件的元素上。因此,就会产生问题,比如,在给

此处我们以Vant UI组件库的van-button为例,根据自己的样式需求修改该组件的样式,以达到我们的要求,同时其他组件的van-button样式不受此组件影响。具体写法如下:

<template>
      <div class="btn">
      <van-button type="primary">按钮</van-button>
    </div>
</template>

<style lang="scss" scoped>
  .btn {
    :deep(.van-button) {
      background-color: red;
    }
  }
</style>

提示:通过 v-html 创建的 DOM 内容不会被作用域样式影响,但你仍然可以使用深度选择器来设置其样式。

三、插槽选择器

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

// 父组件
<template>
  <div>
    <Child>
      <template #default>
        // p标签的内容显示红色
        <p class="text">我是子组件插槽内容</p>
      </template>
    </Child>
  </div>
</template>
<script lang="ts" setup>
import Child from './child.vue';
</script>
// 子组件
<template>
    <div class="child">
        <div>我是子组件</div>
        <slot />
    </div>
</template>

<style lang="scss" scoped>
.child {
    :slotted(p.text) {
        color: red;
    }
}
</style>

四、全局选择器

如果想让其中一个样式规则应用到全局,比起另外创建一个style,可以使用 :global 伪类来实现。看如下代码:

<style lang="scss" scoped>
  :global(p) {
    color: red;
  }
</style>

此时,项目中所有组件的 p 标签的字体颜色都会显示红色。

五、混合使用局部与全局样式

为了满足不同的代码需求,可以在同一个组件中同时包含作用域样式和非作用域样式。

<template>
    <div>
        
    </div>
</template>

<style>
    /* global styles */
    /* 对全局组件有效 */
</style>

<style scoped>
    /* local styles */
    /* 样式只对该组件有效 */
</style>

六、支持style module

style标签的module属性是很有意思的。

当我们需要对一个模板遍历多次,并且需要动态地显示css,比如,一个列表根据状态的不同显示不同的css样式,此时,style module 会比 v-bind 绑定 style 样式或者 class 类名来得更方便。

<template>
    <div>
        <p :class="$style.red">我是内容</p>
    </div>
</template>

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

写了 module 就不需要在 style 标签上写 scoped 属性了

七、自定义注入名称

我们还可以给style module属性自定义注入类对象的 property 键,也就是给module属行自定义一个名字。

<template>
    <div>
        <p :class="classes.red">我是内容</p>
    </div>
</template>

//  给classes自定义一个classes的名字
<style lang="scss" module="classes">
    .red {
        color: red;
    }
</style>

八、与组合式 API 一同使用

注入的类可以通过 useCssModule API 在 setup() 和

// 默认, 返回 <style module> 中的类
useCssModule()

// 命名, 返回 <style module="classes"> 中的类
useCssModule('classes')

对于 JSX/TSX 组件,由于其没办法用 scoped style,所以 CSS Modules 是个很好的选择。

<script lang="tsx">
import { defineComponent, useCssModule } from 'vue';
export default defineComponent({
  setup(){
        const classes = useCssModule('classes');

    return () => (
      <>
        <div class={ classes.text }>我是内容</div>
      </>
    );
  }
})
</script>

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

九、状态驱动的动态 CSS

状态驱动的动态 CSS 我觉得是一个很实用的特性,可以在style内通过 v-bind CSS 函数将 CSS 的值链接到动态的组件状态,可以通过v-bind 绑定 script 中的属性和变量。

实际的值会被编译成哈希化的 CSS 自定义属性,因此 CSS 本身仍然是静态的。自定义属性会通过内联样式的方式应用到组件的根元素上,并且在源值变更的时候响应式地更新。

<template>
  <p>hello</p>
</template>

<script setup>
const theme = {
  color: 'red'
}
</script>

<style scoped>
p {
  // 绑定theme.color变量
  color: v-bind('theme.color');
}
</style>
目录