Vue 组件间的样式处理 -- scoped

关于 vue 组件间的样式问题,一直困扰我。父与子,子与父,兄弟组件间相互的样式污染,再加上 scoped 作用域的作用,导致我们很难搞清楚之间的相互关系,今天我们就来一探究竟;

1.父子组件之间的样式

// 父组件
<div id="app">
    <h2>父组件的h2</h2>
    <h3>父组件的h3</h3>
    <ChildCom/>
</div>
<style>
h2 {
  background-color: red;
}
</style>

// 子组件
<div id="ChildCom">
    <h2>ChildCom子组件的h2</h2>
    <h3>ChildCom子组件的h3</h3>
</div>
<style>
h2 {
  background-color: blue;
}
</style>
  • 父组件有一个 h2 和 h3 标签,并引入 ChildCom 子组件,在 style 里面定义 h2 的样式;
  • 子组件同样也有 h2 和 h3 标签,在 style 里面定义 h2 的样式;

通过现象可以看到,父组件的样式覆盖了子组件的样式;但是为什么会这样呢?按照我的理解,每个 vue 组件都有自己的生命周期,父组件在执行自己的生命周期时,发现需要加载子组件,于是父组件等待子组件执行自己的生命周期,待子组件加载完毕之后,父组件接着执行完自己的生命周期(父组件的生命周期先开始但是后结束)。所以在这个过程中,子组件的样式先加载,父组件的样式后加载,于是父组件的样式覆盖了子组件的样式。

2.兄弟组件之间的样式

// ChildCom
<div id="ChildCom">
    <h2>ChildCom子组件的h2</h2>
    <h3>ChildCom子组件的h3</h3>
</div>
<style>
h2 {
  background-color: blue;
}
</style>

// OtherChildCom
<div class="OtherChildCom">
    <h2>OtherChildCom子组件的h2</h2>
    <h3>OtherChildCom子组件的h3</h3>
</div>
<style>
h2 {
  background-color: red;
}
</style>

// 父组件
<div id="app">
    <ChildCom/>
    <OtherChildCom/>
</div>

ChildCom 组件里面设置 h2 的背景颜色为蓝色,OtherChildCom 组件里面设置 h2 的背景颜色为红色;

我们可以看到 OtherChildCom 里面的样式覆盖了 ChildCom 的样式。这和组件的加载顺序(import的顺序,不是在html里面的顺序)有关;如果我们更换子组件的加载顺序,那么 ChildCom 的样式会覆盖 OtherChildCom;

3.使用scoped属性

scoped 属性会给当前组件的根元素、组件自身的后代元素和子组件的根元素添加一个 data-v-x 属性。

// 父组件
<div id="app">
    <h2>父组件的h2</h2>
    <h3>父组件的h3</h3>
    <ChildCom/>
</div>
<style scoped>
</style>

// 子组件
<div id="ChildCom">
    <h2>ChildCom子组件的h2</h2>
    <h3>ChildCom子组件的h3</h3>
</div>
<style>
</style>

父组件 style 标签中有 scoped 属性,子组件的 style 标签中没有 scoped 属性,于是在 html 中的体现如下:

我们看到父组件的根元素,父组件的后代元素以及子组件的根元素上都被添加上了 data-v-x 属性;

如果父子组件的style标签上都加了 scoped 属性呢?

我们看到这时子组件的根元素和子组件的后代元素上也都添加上了 data-v-x 属性,这样子元素的根元素上就被添加上了两个data-v-x属性;

接下来我们来探讨对具体样式的影响:

  • 我们仅仅给父元素添加scoped属性

// 父组件
<div id="app">
    <h2>父组件的h2</h2>
    <h3>父组件的h3</h3>
    <ChildCom/>
</div>

<style scoped>
h3 {
  background-color: red;
}
</style>

// 子组件
<div id="ChildCom">
    <h2>ChildCom子组件的h2</h2>
    <h3>ChildCom子组件的h3</h3>
</div>

<style>
h3 {
  background-color: blue;
}
</style>

父组件的 scoped 标签会在 css 上生成相应的属性原则器,这样父组件的样式就不会作用到子组件上了。

  • 同样,我们给子组件上添加 scoped 属性;
// 父组件
<div id="app">
    <h2>父组件的h2</h2>
    <h3>父组件的h3</h3>
    <ChildCom/>
</div>

<style>
h3 {
  background-color: red;
}
</style>

// 子组件
<div id="ChildCom">
    <h2>ChildCom子组件的h2</h2>
    <h3>ChildCom子组件的h3</h3>
</div>

<style scoped>
h3 {
  background-color: blue;
}
</style>

同样,子组件上回生成相对应的属性选择器,一样也不会作用到父元素。

  • 如果同时给父子组件都加上 scoped 属性呢?

父子组件会生成各自对应的属性选择器,这样父子组件之间不会被相互影响。

  • 如果我们想通过父组件来修改子组件的样式,我们可以通过">>>" 或者 /deep/ 来修改
// 父组件
<div id="app">
    <h2>父组件的h2</h2>
    <h3>父组件的h3</h3>
    <ChildCom/>
</div>

<style scoped>
#app >>> h3 {
  background-color: red;
}
</style>

// 子组件
<div id="ChildCom">
    <h2>ChildCom子组件的h2</h2>
    <h3>ChildCom子组件的h3</h3>
</div>

<style scoped>
h3 {
  background-color: blue;
}
</style>

// 父组件
<div id="app" class="app">
    <h2>父组件的h2</h2>
    <h3>父组件的h3</h3>
    <ChildCom/>
</div>

<style scoped>
.app >>> h3 {
  background-color: red;
}
</style>

// 子组件
<div id="ChildCom">
    <h2>ChildCom子组件的h2</h2>
    <h3>ChildCom子组件的h3</h3>
</div>

<style scoped>
#ChildCom h3 {
  background-color: blue;
}
</style>

该操作会增加选择器的权重,来让父组件的样式覆盖到子组件;

  • 如果我们对代码稍作修改,样式又会发生变化
// 父组件
<div id="app" class="app">
    <h2>父组件的h2</h2>
    <h3>父组件的h3</h3>
    <ChildCom/>
</div>

<style scoped>
.app >>> h3 {
  background-color: red;
}
</style>

// 子组件
<div id="ChildCom">
    <h2>ChildCom子组件的h2</h2>
    <h3>ChildCom子组件的h3</h3>
</div>

<style scoped>
#ChildCom h3 {
  background-color: blue;
}
</style>

因为这时候父组件选择器的权重还是没能干过子组件选择器的权重,于是还是会显示子组件的样式。

猜你喜欢

转载自blog.csdn.net/josavion/article/details/112869961