Allen's blog Allen's blog
首页
面经
算法 (opens new window)
分类

Allen

前端CV工程师
首页
面经
算法 (opens new window)
分类
  • Javascript

  • TypeScript

  • CSS

  • Vue

    • Vue样式scoped原理以及样式穿透原理
      • 举例说明
    • inject响应式怎么做
    • Vue状态管理工具Vuex
    • Vue状态管理工具Pinia
    • Vue重用的组件中使用有状态methods(如防抖)有问题
    • vue3 props unknown属性上不存在xxx
    • Vuex中的状态如果是引用类型,没有响应式
    • typescript类型Element转化为HTMLElement
  • React

  • 框架和构建工具

  • 工具库

  • 常见业务场景

  • Bug

  • 项目实战

  • 前端
  • Vue
Allen
2023-03-24
目录

Vue样式scoped原理以及样式穿透原理

构建工具调用相应的处理器(loader),当 SFC 组件是 style 标签包含 scoped 属性时,处理器会给组件的 DOM 节点和子组件添加自定义属性data-v-xxx,子组件只会在最外层 DOM 节点添加自定义属性data-v-xxx,然后会给组件内 CSS 选择器之后添加对应的属性选择器[data-v-xxx]。

# 举例说明

父组件 template 内容:

<template>
    <div>
        <span>Hello World! I'm father!</span>
        <span>I love coding.</span>
        <SonComponent></SonComponent>
    </div>
</template>
<style>
span {
    color: red;
    }
.hobby{
    background-color: yellowgreen;
    }
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

子组件 template 内容:

<template>
    <div>
        <div>Hello, I'm son!</div>
        <div class="hobby">I love painting.</div>
    </div>
</template>
<style>
div {
    color: blue;
}
.hobby{
    background-color: pink;
}

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

如果父组件和子组件都没有在 style 标签上添加 scoped 属性,渲染后的结果是:

<div>
    <span>Hello World! I'm father!</span>
    <span>I love coding.</span>
    <div>
        <div>Hello, I'm son!</div>
        <div>I love painting.</div>
    </div>
</div>
1
2
3
4
5
6
7
8

给父组件和子组件 style 标签添加 scoped 属性,渲染的结果是:

<div data-v-938b83b0>
    <span data-v-938b83b0>Hello World! I'm father!</span>
    <span data-v-938b83b0>I love coding.</span>
    <div data-v-938b83b0 data-v-fb8c5270>
        <div data-v-fb8c5270>Hello, I'm son!</div>
        <div data-v-fb8c5270>I love painting.</div>
    </div>
</div>
1
2
3
4
5
6
7
8
div[data-v-f2eb8ef8]{color:#00f}
.hobby[data-v-f2eb8ef8]{background-color:pink}
span[data-v-080e8582]{color:red}
.hobby[data-v-080e8582]{background-color:#9acd32}
1
2
3
4

此时,如果想修改子组件的样式,只能修改子组件最外层元素样式,无法修改子组件内部的元素的样式,因为父组件中,所有 CSS 选择器的后面都添加了父组件的自定义属性data-v-f2eb8ef8,只有拥有属性data-v-f2eb8ef8的元素才能应用父组件 CSS 选择器中的样式,子组件中除了子组件最外层元素,都没有data-v-f2eb8ef8属性。

要想改变子组件内部的样式,在 vue3 中需要在选择器使用:deep()包裹,生成的 CSS 会将data-v-f2eb8ef8提到选择器前方,而不是后方,此时,子组件最外层元素是有data-v-f2eb8ef8属性的,因此能够实现选择子组件的元素,实现样式穿透。

div[data-v-f2eb8ef8] {color:#00f}
.hobby[data-v-f2eb8ef8] {background-color:pink}
span[data-v-0a512275] {color:red}
[data-v-0a512275] .hobby{background-color:#9acd32}
1
2
3
4

样式穿透不仅可以穿透子组件,还可以穿透深层的后代组件

上次更新: 2023/12/16, 09:22:46
B站付金权直播课tailwind
inject响应式怎么做

← B站付金权直播课tailwind inject响应式怎么做→

最近更新
01
rollup使用配置文件rollup.config.ts打包
12-08
02
package.json导出类型
12-08
03
关键问题方案
11-17
更多文章>
Theme by Vdoing | Copyright © 2023-2023 Allen | Github
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式