vue中css的scoped和deep解析

[TOC]

vue loader官网

scoped的作用

  • 官方解释:当 <style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素,即它不影响外面,外面的也不影响里面,不过外面的样式可以通过继承影响里面的样式。
  • 深度解析:scoped的作用是编译后给当前组件每个dom加一个独有的hash值 (data-v-xxxx),假定为data-v-father,并且它的子组件的根元素也会加上这个hash值data-v-father,如果子组件style也是用来scoped则子组件每个dom元素也都有一个自己的hash值假定为data-v-child,所以子组件的根元素是有两个hash值的data-v-father和data-v-child.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 父组件
<template>
<div id="app">
<img width="25%" src="./assets/logo.png">
<HelloWorld/>
</div>
</template>
<style scoped>
</style>
------------------------------------------------------------------------
// 子组件
<template>
<div class="child-wrap">
<div class="child">sdfjhasfhjasdfj</div>
<span>4234</span>
</div>
</template>
<style scoped>
</style>

编译后:(父组件hash是data-v-7ba5bd90,子组件hash是data-v-763db97b)

1
2
3
4
5
6
7
<div data-v-7ba5bd90 id="app">
<img data-v-7ba5bd90 width="25%" src="">
<div data-v-763db97b data-v-7ba5bd90 class="child-wrap">
<div data-v-763db97b class="child">sdfjhasfhjasdfj</div>
<span data-v-763db97b>4234</span>
</div>
</div>
  • scoped的效果会使得编译后的style中每个类名后面都会加上当前组件的hash值,如:.classA[data-v-father],注意中间没有空格
1
2
3
4
5
6
7
8
9
10
11
12
<style lang="less" scoped>
#app {
.child2 {
color: blue;
}
}
.child-wrap {
height: 300px;
}
</style>

编译后(当前组件hash值为data-v-7ba5bd90):

1
2
3
4
5
6
7
8
<style>
#app .child2[data-v-7ba5bd90] {
color: blue;
}
.child-wrap[data-v-7ba5bd90] {
height: 300px;
}
</style>

deep的作用

  • 官方解释:如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符,有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/::v-deep 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作

  • 深度解析:上面讲了scoped的作用是使的每个组件内的class编译后都会在后面加上一个hash值,这样在父组件里即使写了子组件某个class,它编译后跟子组件的class也是不一样的。因此,如果需要在父组件里覆盖子组件的样式,除了使用全局class,还可以用deep

    deep的作用是在当前class前加上一个当前组件的hash值,并且去掉了scoped在后面加hash值的效果,如[data-v-father] .classA,注意中间是有空格的,由于子组件的根元素上是打了父组件hash值的,所以[data-v-father] .classA是可以定位到子组件上.classA元素的。

  • 注意:deep保险的使用方法是前面要加上上层选择器的,如.wrap /deep/ .classA{},如果deep前面不加上层选择器

1
/deep/ .classA {}

不同的loader版本会编译成不同的情况:

1
2
3
4
5
有的deep是生效的,编译结果是
[data-v-7ba5bd90] .classA{} // 中间有空格
有的编译出来中间空格没了,deep的效果就不生效
[data-v-7ba5bd90].classA{} // 中间没有空格
1
2
3
4
5
6
7
<style scoped>
#app {
/deep/ .child {
height: 200px;
}
}
</style>

将会编译成

1
2
3
4
5
<style>
#app[data-v-7ba5bd90] .child {
height: 200px;
}
</style>

####

演示代码详见:https://codesandbox.io/s/mo184r48q9

热评文章