在使用scoped遇到的一些问题

场景

在子组件中用到了ele-uiel-scrollbar(自定义滚动的隐藏组件,官方无文档说明,可以在其他地方搜到使用方法),如图:

(忽略图里的null)

style样式如下:
ele-ui自带样式

此处期望修改为X轴无滚动条,Y轴显示自定义滚动条:
期望效果

直接修改样式

然而直接在子组件里添加代码下方代码,并未生效(子组件style添加了scoped属性)。同时在控制台styles中并未找到对应样式设置。

.el-scrollbar__wrap {
  overflow-y: scroll;
  overflow-x: hidden;
}

然后尝试将此段代码添加到公共样式中,生效。

问题

scoped究竟有何作用?el-scrollbar在子组件里使用,子组件中设置el-scrollbar__wrap的样式却无效?如何解决这个问题?

求解

官方文档,有作用域的 CSS

  • <style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。
  • 通过 v-html 创建的 DOM 内容不受作用域内的样式影响,但是你仍然可以通过深度作用选择器来为他们设置样式。
  • 有些像 Sass之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 操作符取而代之——这是一个>>> 的别名,同样可以正常工作。

在上面场景中,el-scrollbar虽然是在子组件中使用,但是el-scrollbar__wrap却是动态生成的DOM元素,如果要在子组件中设置需要使用深度作用选择器>>>(或/deep/) 。此处子组件style设置了lang="scss",上述代码修改如下:

/* .el-scrollbar 为原有的DOM元素 */
.el-scrollbar {
  &/deep/ .el-scrollbar__wrap {
    overflow-y: scroll;
    overflow-x: hidden;
  }
}

同时删除了公共样式中相关样式设置。然后运行,达成预期。

当然文档里同样说明在一个组件中可以同时使用有作用域和无作用域的样式。另一种方案则是此组件中另写个全局样式标签,并将需要设置的样式放入其中。(并不能感觉和最初有啥区别,都是设置全局)

其它

scoped属性可以理解为组件样式的私有化,其设置的样式只对当前组件有效,即只对组件中的DOM元素有效(包括组件中用到的子组件的根元素)。
有组件About.vue如下:

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <!-- 组件c-div -->
    <c-div class="cdiv"></c-div>
  </div>
</template>
<script>
import Cdiv from "@/views/Cdiv";
export default {
  data() {
    return {};
  },
  components: {
    "c-div": Cdiv
  }
};
</script>

<style lang="scss" scoped>
h1 {
  color: red;
}
.cdiv {
  width: 100px;
  height: 100px;
  margin: 0 auto;
  border: 1px solid #000;
  h3 {
    color: red;
  }
}
</style>

下面的是子组件Cdiv.vue

<template>
  <div class="about">
    <h3>这是组件C</h3>
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  components: {}
};
</script>

<style lang="scss" scoped>
h3 {
  color: blue;
}
</style>

在不使用深度作用选择器的情况下,About.vue样式可以影响到c-div,却不会影响c-div下面的子元素

在浏览器下查看DOM结构,不难发现scoped设置组件样式私有化,是通过给DOM元素添加对应属性(如data-v-039c5b43),并在对应样式中添加对应属性选择器,由于不同组件之间的属性是不同的,因此可以实现样式私有化控制。

通过PostCSS对内容进行转换

Cdiv.vuestyle标签的scoped移除,并添加插槽:

    <c-div class="cdiv">
      <h3>about</h3>
    </c-div>
依然没有影响到c-div组件中的子元素


在没有使用深度作用选择器的情况下,属性会添加到样式直接作用的具体元素,无论是子组件的子元素,还是后续动态添加的元素都无法在PostCSS转换的时候被添加对应属性(还不存在),因此scoped对子元素或动态添加的元素无效。深度作用选择器有点像属性委托,将被直接作用到的子元素的的属性委托到其父元素上,如解决方案中修改后的样子:
属性添加到.el-scrollbar上而不是添加到其子元素上

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。