Scoped 与 样式穿透

发布于 2024-06-11 20:57:31 字数 4692 浏览 16 评论 0

Scoped 的原理

vue 中的 scoped 通过在 DOM 结构以及 CSS 样式上加唯一不重复的标记 data-v-hash 的方式,以保证唯一(而这个工作是由过 PostCSS 转译实现的),达到样式私有化模块化的目的。

scoped 三条渲染规则:

  1. 给 HTML 的 DOM 节点加一个不重复 data 属性(形如 data-v-123 ) 来表示他的唯一性
  2. 在每句 CSS 选择器的末尾(编译后的生成的 css 语句)加一个当前组件的 data 属性选择器(如 [data-v-123])来私有化样式
  3. 如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的 data 属性

PostCSS 会给一个组件中的所有 dom 添加了一个独一无二的动态属性 data-v-xxxx ,然后,给 CSS 选择器额外添加一个对应的属性选择器来选择该组件中 dom,这种做法使得样式只作用于含有该属性的 dom——组件内部 dom, 从而达到了'样式模块化'的效果.

使用 Scoped ,在进行 PostCss 转化的时候把元素选择器默认放在了最后

img

Vue 提供了样式穿透 :deep() 他的作用就是用来改变 属性选择器的位置

img

img

:slotted 插槽选择器

A 组件定义一个插槽

<template>
    <div>
        我是插槽
        <slot></slot>
    </div>
</template>
 
<script>
export default {}
</script>
 
<style scoped>
 
</style>

在 App.vue 引入

<template>
    <div>
        <A>
            <div class="a">....</div>
        </A>
    </div>
</template>
 
<script setup>
import A from "@/components/A.vue"
</script>
 
<style lang="less" scoped>
</style>

在 A 组件修改 class a 的颜色,无效果

<style scoped>
.a{
    color:red
}
</style>

默认情况下,作用域样式不会影响到 <slot/> 渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。

解决方案 slotted

<style scoped>
 :slotted(.a) {
    color:red
}
</style>

:global 全局选择器

在之前我们想加入全局样式,通常都是新建一个 style 标签,不加 scoped。

<style>
 div{
     color:red
 }
</style>
 
<style lang="less" scoped>
 
</style>

现在有更优雅的解决方案

<style lang="less" scoped>
:global(div){
    color:red
}
</style>

动态 CSS

单文件组件的 <style> 标签可以通过 v-bind 这一 CSS 函数将 CSS 的值关联到动态的组件状态上:

<template>
    <div class="div">
       ....
    </div>
</template>
 
<script lang="ts" setup>
import { ref } from 'vue'
const red = ref<string>('red')
const blue = ref({
    color:'blue'
})
</script>
 
<style lang="less" scoped>
  .div{
    color:v-bind(red);
    background: v-bind('blue.color'); /* 是对象 v-bind 加引号 */
  }
</style>

css module

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

<template>
    <div :class="$style.red">
        ...
    </div>
</template>
 
<style module>
.red {
    color: red;
    font-size: 20px;
}
</style>

自定义注入名称(多个可以用数组),通过给 module attribute 一个值来自定义注入的类对象的 property 键

<template>
    <div :class="[zs.red,zs.border]">
        小满是个弟弟
    </div>
</template>
 
<style module="zs">
.red {
    color: red;
    font-size: 20px;
}
.border{
    border: 1px solid #ccc;
}
</style>

与组合式 API 一同使用

使用场景一般用于 TSXrender 函数 居多

注入的类可以通过 useCssModule API 在 setup()<script setup> 中使用。对于使用了自定义注入名称的 <style module> 模块, useCssModule 接收一个对应的 module attribute 值作为第一个参数

<template>
    <div :class="[zs.red,zs.border]">
        ...
    </div>
</template>
 
<script setup lang="ts">
import { useCssModule } from 'vue'
const css = useCssModule('zs')
</script>
 
<style module="zs">
.red {
    color: red;
    font-size: 20px;
}
.border{
    border: 1px solid #ccc;
}
</style>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

高冷爸爸

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

玍銹的英雄夢

文章 0 评论 0

我不会写诗

文章 0 评论 0

十六岁半

文章 0 评论 0

浸婚纱

文章 0 评论 0

qq_kJ6XkX

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文