1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > vue的scoped 样式隔离 样式穿透 及细节

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

时间:2022-08-19 19:59:03

相关推荐

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结果

效果图

可以看到

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

小细节:

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]{......},故而不会受到影响。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。