vue的scoped 样式隔离,样式穿透,及细节

先说环境吧:vue 3.2.45,也试过vue 3.2.16

vue的scoped样式隔离

原理:

在当前组件的.vue文件中,如果style标签加了scoped属性,那么在组件渲染为DOM时,会对每个组件中的DOM元素添加格式为:data-v-[hash:8]的属性,然后该组件的所有`选择器`也会添加上对应的`[data-v-[hash:8]]`属性选择器来只对自身组件产生影响。以此来实现样式隔离。例子如下:

父组件:App.vue

<script>
import Comp from './Comp.vue';
export default {
  components:{
    Comp
  },
  data() {
    return {
      msg: 'Hello World!'
    }
  }
}
</script>

<template>
  <p>{{ msg }}
  	
  </p>
  <Comp/>
</template>

<style scoped>
  p{
    color:red;
  }

</style>

子组件:Comp.vue

<script>
export default {
  data() {
    return {
      
    }
  }
}
</script>

<template>
  <div>
    <p>
    	In Comp
  	</p>
  </div>
  <p>
    	In Comp
  </p>
  
</template>
<style scoped>
  p{
    font-size:20px;
    color:blue;
  }
</style>

DOM结果

效果图

 可以看到

  1. 子组件Comp多了data-v-37b1dc3d属性,父组件App多了data-v-472cff63,并且style也设置了属性选择器
  2. 由于属性选择器的缘故,实现了样式隔离。

小细节:

1. 如果父组件App.vue不设置scoped会怎么样

假设App.vue的style和Comp.vue的style如下

<!--App.vue  -->

<style>
  p{
    color:red;
  }
</style>

<!-- Comp.vue -->
<style scoped>
  p{
    font-size:20px;
  }
</style>

父组件的样式就成了全局的样式了。

2. 如果父组件App.vue和子组件Comp.vue都不设置scoped会怎么样

 

看结果就知道,俩组件的样式都成了全局的了

3. 注意样式继承

1的基础上,首先父组件和子组件的样式都设置上scoped属性。然后父组件App.vue的template如下

<template>
  <p>{{ msg }}
  	<Comp/>
  </p>
  <Comp/>
</template>

 结果就是

 即使是样式隔离也要注意 样式继承

样式穿透的细节

1. 子组件的单节点和多节点

代码如下

<!--App.vue -->
<script>
import Comp from './Comp.vue';
export default {
  components:{
    Comp
  },
  data() {
    return {
      msg: 'Hello World!'
    }
  }
}
</script>

<template>
  <p>{{ msg }}
  	
  </p>
  <Comp/>
</template>
<style scoped>
  p{
    color:red;
  }
</style>

<!--Comp.vue -->
<script>
export default {
 
  data() {
    return {
     
    }
  }
}
</script>

<template>
  
  <p>
    In Comp
  </p>
  <p>
    In Comp
  </p>
  
</template>
<style scoped>
  p{
    font-size:20px;
  }
</style>

 这里Comp.vue的template包含了俩p标签,结果如下

能看出来,正常的实现样式隔离,不同组件各加各的data-v-[hash]属性

但是!

如果子组件只有一个p标签,其他条件不变时:

<template>
  
  <p>
    In Comp
  </p>
  
</template>

结果却是:

         

                                       

 这就很有意思了。   

如果说把Comp.vue的template设置如下:                                   

<template>
  <div>
      <p>
        In Comp
      </p>
  </div>
 
</template>

 结果则是

             

                                           

更进一步的,如果说把Comp.vue的template设置如下

<template>
  <div>
      <p>
        In Comp
      </p>
  </div>
  <div>
      <p>
        In Comp
      </p>
  </div>
</template>

 

总结

这么多次对比试验能看出来,当子节点为单节点时,由于template标签并不会出现在DOM树中,所以那个单节点就会同时具有父组件和子组件的data-v-[hash]属性。如果是多节点,则只会有组件自身的data-v-[hash]属性。有必要去看看vue源码了。

要说这个细节有啥用嘛。。。emmmmmm。。。就当注意一下比较好。假如父组件想自己的p标签字体是红色,子组件为默认颜色。那如果子组件不套一个div或者是一个单独的p标签,就会被父组件的样式所影响。以此类推到别的标签也是同理

2. 样式穿透

不想截图了。。。

样式穿透所使用的/deep/也好,>>> 也好。最后会被渲染为父组件的data-v-[hash]。也就是说,假设父组件的style为:>>> p{color:blue},想用来改变子组件的p标签字体颜色来实现样式穿透。那么必须要保证子组件的template只有一个子节点,即上述的单个根节点情况因为,单根节点(假设为div)会同时具有父组件和子组件的data-v-[hash]。

又因为/deep/也好,>>> 也好。最后会被vue更改为父组件的data-v-[hash](假设为data-v-123456)。此时就能通过[data-v-123456] p{color:blue;}改变子组件p标签的字体颜色。而由于父组件其他的DOM,如某一个p标签,其选择器为p[data-v-123456]{......},故而不会受到影响。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue中,scoped样式是一种给组件的样式添加作用域的方式,让样式在组件内起作用,不会影响到其他组件。然而,有时候我们希望某个组件的样式作用于其子组件或者父组件,这就需要穿透scoped样式。 对于子组件,我们可以通过使用`/deep/`或者`>>>`来穿透scoped样式。例如,在父组件的样式中,可以这样定义: ``` <style scoped> .parent /deep/ .child { color: red; } </style> ``` 在上面的例子中,`.parent`是父组件的样式,而`.child`是子组件的样式。使用`/deep/`可以让`.child`样式作用于子组件。 对于父组件,如果想要穿透scoped样式,可以通过将样式定义在全局样式中,或者使用`>>>`。例如,在子组件中,可以这样定义: ``` <template> <div class="parent"> <div class="child">子组件样式</div> </div> </template> <style scoped> .child { color: red; } .parent >>> .child { color: blue; } </style> ``` 在上面的例子中,`.child`是子组件的样式,`.parent`是父组件的样式。使用`>>>`可以让`.child`样式作用于父组件。 需要注意的是,`/deep/`和`>>>`只在一些支持CSS Modules的构建工具中生效,例如vue-loader。如果在其他环境中使用,可能无法生效。 总结:通过使用`/deep/`或者`>>>`,我们可以穿透Vuescoped样式,让样式作用于子组件或者父组件。但是需要注意,这种方式只在部分构建工具中生效,不同环境可能会有差异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值