个人博客 个人博客
首页
  • 前端
  • 后端
  • Git
  • Docker
  • 网络
  • 操作系统
工具
阅读
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

董先亮

前端react开发
首页
  • 前端
  • 后端
  • Git
  • Docker
  • 网络
  • 操作系统
工具
阅读
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Vue

    • 响应式API
    • vite环境变量
    • 侦听
    • 样式
    • 多环境配置
    • 实现页面缓存
    • 组件封装
    • nextTick
    • 组件传值
    • 批量导入
    • 插槽
    • scoped与deep原理
      • 前置知识
        • CSS属性选择器
      • scoped原理
      • scoped产生的影响
      • vue中深度选择器
    • v-model
    • vue-router
    • 项目全局
    • 自定义hook
  • React

  • 前端框架
  • Vue
NeverStop1024
2023-02-08
目录

scoped与deep原理

# 前置知识

# CSS属性选择器 (opens new window)

HTML允许给DOM元素设置属性(<p bg-red>属性</p>)或属性值(<p data=“red”>属性值</p>),通过属性进一步选择元素,修改其样式。

<!DOCTYPE html>
<html>
<head>
  <style>
    p[bg-red] {
      background-color: red;
    }

    p[fontColor="red"] {
      color: red;
    }
  </style>
</head>
<body>
  <p bg-red>文本一</p>
  <p fontColor="red">文本二</p>
</body>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

效果如图: image.png

# scoped原理

vue中scoped主要通过postcss (opens new window)实现的,转译代码时postcss做了如下处理:

  1. 给每个DOM节点添加一个唯一的属性(如:data-v-a0901)
  2. 在css选择器末尾加上对应的属性选择器(如:.user[data-v-a0901]),来私有化样式

如果组件内包含其他组件,只会给其他组件的最外层标签加上当前组件的data属性

转译前

<style scoped lang="sass">
  .example {
    color: red;
  }
</style>
<template>
  <div class="example">scoped测试案例</div>
</template>
1
2
3
4
5
6
7
8

转译后

<style scoped lang="sass">
  .example[data-v-5558831a] {
    color: red;
  }
</style>
<template>
    <div class="example" data-v-5558831a>scoped测试案例</div>
</template>
1
2
3
4
5
6
7
8

这样也就达到了样式模块化的目的。

# scoped产生的影响

当我们想去改组件库样式(如elementUI)时,会发现修改不成功了。

<style lang="scss" scoped>
.container{
  background: #fff;
  .ep-rate{
    background: black;
    .ep-rate__item{
      background: red;
    }
  }
}
</style>
1
2
3
4
5
6
7
8
9
10
11

转译后

.container[data-v-7ba5bd90] { background: #fff; } 
.container .ep-rate[data-v-7ba5bd90] { background: black; } 
.container .ep-rate .ep-rate__item[data-v-7ba5bd90] { background: red; }
1
2
3

这时候会发现,想要改组件库的样式改不掉了,只改掉了第一层,因为引入其他组件,只会在最外层加上私有属性,所以ep-rate的样式可以修改成功。

image.png

image.png 那在scoped中如何修改组件库样式呢?这就要用到深度选择器了,继续往下看。

# vue中深度选择器

deep的原理就是将私有属性移到上一层

<style lang="scss" scoped>
// .container[data-v-7ba5bd90]
.container{
  background: #d7d7d7;
  // .container .box2[data-v-7ba5bd90]
  .box2{
    width:100px;
    height: 100px;
    // .container .box2 .ep-button[data-v-7ba5bd90]
    .ep-button{
      background: red;
    }
    // .container .box2[data-v-7ba5bd90] .ep-button
    :deep(.ep-button){
      background: #00a6ff;
      border: none;
    }
  }
  :deep{
    // .container[data-v-7ba5bd90] .ep-rate
    .ep-rate{
      background: #000000;
      // .container[data-v-7ba5bd90] .ep-rate .ep-rate__item
      .ep-rate__item{
        background: #4eff10;
      }
    }
  }
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

可以看到,加deep深度选择器后,deep内的class都没加私有属性,而是把私有属性提升到了deep的上一层,这样就可以修改组件库样式了。

编辑 (opens new window)
上次更新: 2023/02/08
插槽
v-model

← 插槽 v-model→

最近更新
01
mock使用
07-12
02
websocket即时通讯
07-12
03
前端面试题
07-09
更多文章>
Theme by Vdoing | Copyright © 2022-2023 NeverStop1024 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式