vue中使用scoped防止样式污染以及scoped的原理

本文探讨了Vue中样式污染的问题,并介绍了如何通过使用scoped来防止样式冲突。详细阐述了不同情况下,如父组件和子组件是否使用scoped时的样式作用范围,解释了scoped的工作原理,即通过为组件添加唯一ID实现样式私有化。

样式污染示例

一个很简单的例子,在两个组件中都有class名为test的div标签,在ScopedDemo组件中设置test样式,在ScopedChildCpm中没有设置样式。

<template>
  <div class="scoped-test-wrap">
    <div class="test">样式污染</div>
    <ScopedChildCpm></ScopedChildCpm>
  </div>
</template>
<script>
import ScopedChildCpm from "./ScopedChildCpm.vue";
export default {
  name: "ScopedDemo",
  components: { ScopedChildCpm },
};
</script>
<style>
.test {
  width: 100px;
  height: 50px;
  background-color: gold;
  margin: 10px;
}
</style>
<template>
  <div class="test">child组件</div>
</template>

<script>
export default {
  name: "ScopedChildCpm",
};
</script>
<style>

</style>

当运行程序,在浏览器中可以看到,两个组件的样式都改变了。

如果对ScopedChildCpm组件中的标签也进行样式设置结果会是怎样的,它们会按照自己的样式进行渲染吗?

<template>
  <div class="test">child组件</div>
</template>

<script>
export default {
  name: "ScopedChildCpm",
};
</script>
<style>
.test {
  width: 100px;
  height: 50px;
  background-color: red;
}
</style>

浏览器渲染结果:

可以看到两个div标签都渲染了ScopedChildCpm中的设置的样式。这就是样式污染。一个组件的样式影响了项目中其他组件的样式。

解决方法

虽然我们可以给每一个样式选择器设置不同的名称,但是一个项目通常由多人完成,你无法干预其他同事的代码,所以需要一种方法能使样式之间相互不影响,即使选择器名称相同也不会相互干扰。而scoped就恰好做了这件事。

Scoped

Scoped是组件样式私有化,当一个style标签拥有scoped属性之后,它的css样式就只能作用域当前的组件。

我们先来看下使用scoped和不使用scoped的区别。

不实用scoped:

 使用scoped:

可以看到style标签使用了scoped属性之后,编译之后每个组件的标签都添加了一个data-v-xxx的属性,其中data-v-xxx是scopedId,每个Vue文件都会对应一个唯一的id,该id是根据文件路径名和内容hash生成,通过组合形成scopedId,所以scopedId也是唯一的,这样不同的组件中的选择器就是唯一的,样式也就不会相互影响,从而得到我们希望的结果。

 父组件和子组件中的几种情况

父组件使用scoped,子组件不使用scoped

先稍微对子组件ScopedChildCpm进行一些修改

<template>
  <div class="child-wrap">
    <div class="test">child组件</div>
    <div class="child-div"></div>
  </div>
</template>

<script>
export default {
  name: "ScopedChildCpm",
};
</script>
<style>
.test {
  width: 100px;
  height: 50px;
  background-color: red;
}
</style>

可以看到父组件使用scoped属性,子组件不使用scoped属性时,只会给子组件最外层的标签添加data-v-xxx动态属性。 

父组件不使用scoped,子组件使用scoped

 可以看到父组件没有动态属性,子组件有动态属性,所以子组件的scoped属性不会影响父组件。

父组件使用scoped,子组件使用scoped 

可以看到子组件的最外层标签添加了两个data-v-xxx动态属性,一个是父组件生成的data-v-xxx,一个是子组件自身生成的data-v-xxx

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值