如果vue组件有带scoped的style,postcss编译时

  1. 会为该组件内所有dom元素都加一个【标识组件唯一】的动态属性[哈希值,data-v-实例标识]
    (这里dom,包括 [普通dom元素] 和 [子组件的根元素] )
  2. 为style<scoped>标签下所有,不包含[deep深度选择器]的选择器最后一级添加属性选择器[哈希值,data-v-实例标识]
<div class="a">
    <div class="b">登录</div>
</div>
<style lang="less" scoped>
.a {
  .b {
    background-color:#bfa
  }
}
</style>

编译后

<div data-v-257dda99b class="a">
    <div data-v-257dda99b class="b">登录</div>
</div>
<style scoped>
.a .b[data-v-257dda99b] {
    background-color:#bfa
}
</style>

deep深度选择器的原理

很简单,vue不会给深度选择器后面的选择器单元增加 属性选择器[哈希值,data-v-实例标识]

深度选择器
css对应 >>>
less/scss等预处理对应 /deep/ , ::v-deep 和最新的 :v-deep()

// 父组件
<template>
    <div class="parent" id="app">
        <h1>我是父组件</h1>
        <child></child>
    </div>
</template>

<style lang="less" scoped>

    // 把子组件的背景变成红色;然而并不起作用
    .child .dyx {
        background-color: red;
    }
    // 加上deep;起作用
    ::v-deep .child .dyx {
        background-color: red;
    }
</style>
// 子组件
<template>
    <div class="child">
        <h1>我是子组件</h1>
        <div class="dyx">
            <p>我是子组件的段落</p>
        </div>
    </div>
</template>

编译后

<div data-v-257dda99b class="parent"  id="app">
    <h1 data-v-257dda99b>我是父组件</h1>
    <div data-v-xxxxxxx class="child">
        <h1 data-v-xxxxxxx>我是子组件</h1>
        <div data-v-xxxxxxx class="dyx">
            <p data-v-xxxxxxx>我是子组件的段落</p>
        </div>
    </div>
</div>

[data-v-257dda99b] .child .dyx {
    background-color: red;
}

.dyx后面的属性选择器没了,所以样式可以正常穿透到子组件生效。
属性选择器[哈希值,data-v-实例标识] 位置 会放在deep深度选择器上一级,确保样式依旧只是局部生效的作用域隔离。


肥皂泡
382 声望6 粉丝

码农