欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue的样式穿透(在父组件中为子组件定义样式)

程序员文章站 2022-03-20 23:29:03
在使用Vue开发前端项目时,我们经常需要引入第三方组件,比如下面的例子(假设我们已经注册了element-ui):这是一个来自element-ui的按钮组件,它会渲染成这样:那我如果我们想修改这个第三方组件的样式该怎么办呢?下面的样式并...

在使用Vue开发前端项目时,我们经常需要引入第三方组件,比如下面的例子(假设我们已经注册了element-ui):

<template>
  <div class="root">
    <el-button type="plain">点击我</el-button>
  </div>
</template>

这是一个来自element-ui的按钮组件,它会渲染成这样:
Vue的样式穿透(在父组件中为子组件定义样式)
那我如果我们想修改这个第三方组件的样式该怎么办呢?

下面的样式并不会生效:

<style scoped>
  .root .el-button--plain {
    font-weight: bold;
  }
</style>

因为el-button--plain对应的标签并不在当前组件作用域内,它在子组件<el-button>的作用域内。

一种非常不优雅的方案是,去掉style的scoped属性,比如:

<style>
  .root .el-button--plain {
    font-weight: bold;
  }
</style>

至于el-button--plain这个类名,需要打开浏览器开发者工具,从element面板中查看。

说到这里,我们需要先了解一下为什么Vue的组件样式推荐添加scoped属性。

我们知道,普通的样式标签内定义的样式对整个页面都是有效的。因此,假如两个组件内存在具有相同类名的标签,那么当我们为其中一个定义样式时,另一个标签的样式也会受到影响(这种影响大多数时候是不利的,因为这种影响不可控)。为了解决这个问题,我们可以在样式标签上添加scoped属性,这样,这个标签内定义的样式只在当前组件内有效。scoped的实现机制为,webpack会在打包时给每个组件的所有标签添加一个特定的属性,如:
Vue的样式穿透(在父组件中为子组件定义样式)
然后,添加了scoped属性的标签内的所有css选择器都会带上这个属性,因此,对于下面的样式:
Vue的样式穿透(在父组件中为子组件定义样式)
编译之后可能是这样的:
Vue的样式穿透(在父组件中为子组件定义样式)
由于只有当前组件内的标签才会携带data-v-752ada3f属性,所以这条样式只会对当前组件内的标签生效。这样就可以保证这条样式只对当前组件内的标签有效。

所以,一旦去掉scoped属性,我们就又回到了原本的问题中。那么如何优雅地解决这个问题呢?

其实可以这样(这里collapse-title是组件内定义的类名,而el-collapse-item__header是组件引用的第三方组件内定义的):
Vue的样式穿透(在父组件中为子组件定义样式)
这里是没有使用css预编译器的写法,>>>表示要穿透组件,使该样式对其子组件生效。它编译后是这样的:
Vue的样式穿透(在父组件中为子组件定义样式)
可以看到,现在只有根选择器带了属性限制,三大于号后面的选择器则没有,这样,el-collapse-item__header就不限制必须属于当前组件了,于是这条属性对子组件内的标签就可以生效了。并且由于scoped属性的存在,这条样式不会影响到其他外部组件(不过如果当前组件的子组件也引用了第三方组件时需要慎重,因为它会继续穿透子组件)。

如果使用了css预编译器,如scss,则需要使用下面的语法:
Vue的样式穿透(在父组件中为子组件定义样式)
这里的/deep/表示这个选择器不属于当前组件,而是属于其子组件,同样可以达到穿透组件修改第三方组件样式的效果。

本文地址:https://blog.csdn.net/qq_41694291/article/details/107498335

相关标签: vue