当前位置: 首页 > article >正文

【Vue中的scoped和 elememt-plus的样式修改】

1. style的scoped属性

scoped属性是为了实现样式隔离,使得组件之间的样式互不影响。
现在我们有
组件A.vue

<template>
  <div class="wrapper">
    <el-statistic :value="output[0]" prefix="" />
    <div class="mt-1 title">本月销售总额</div>
  </div>
</template>

<!-- js代码省略,用不到 -->
<style scoped lang="scss"></style>

这个组件是一个单根组件,外层有一个div包裹,class=wrapper,内部使用了element-plus的数据统计组件el-statistic
这个组件渲染出的DOM元素如下:
在这里插入图片描述
可以发现此时,只有外层容器wrapper上有哈希值:data-v-447f2f22,实际上这个哈希值是A组件父组件的哈希值,如下:
在这里插入图片描述
当前的A组件并没有生成自己的哈希值data-v-xxx,现在只要我们在style内部写入样式代码,即使是注释代码也行,就可以生成A组件自己的哈希值。如下:

<style scoped lang="scss">
//
</style>

在这里插入图片描述

这时候A组件生成了自己的哈希值:data-v-d48692a9(我们暂时不考虑父组件的哈希值)。现在如果我要选中wrapper容器,设置背景色,就可以有如下代码:

<style scoped lang="scss">
//
.wrapper {
  background-color: coral;
}
</style>

实际的选择器为:
在这里插入图片描述
就是把A组件自带的哈希值data-v-d48692a9,加到了选择器上,使用了类选择器加上属性选择器,选中了wrapper容器。如果选择内部的元素,比如 文本 本月销售总额,scss代码如下:

<style scoped lang="scss">
//
.wrapper {
  background-color: coral;

  .title {
    color: red;
  }
}
</style>

对应的DOM元素为:
在这里插入图片描述

实际的css选择器为:

.wrapper .title[data-v-d48692a9] {
    color: red;
}
编译机制解析

.wrapper .title的实际编译结果是.wrapper .title[data-v-d48692a9]
在Vue的scoped样式机制处理后代选择器时,会将data-v-*作用于选择器的最右侧部分(即目标元素),而不是每一级都添加。不仅是目标元素,同时还要是当前组件内部的元素,才会添加这个data-v-*

浏览器在运行时会从右到左解析选择器。

结合scoped编译机制浏览器匹配机制,就可以理解为为什么可以选中对应的元素。

如果最后的目标元素,不是当前组件内部的元素,比如是子组件内部的DOM元素,则 Vue 不会为该元素附加当前组件的 data-v-* 标识。当然,样式匹配不到目标元素。

2. :deep()

:deep() 的作用是让特定的样式可以穿透到子组件的 DOM 中,作用于子组件的某些元素。
比如我们希望在父组件中修改子组件的样式。
示例代码:

子组件test.vue:
<template>
  <div class="test">这里是test组件,是子组件</div>
</template>

<style scoped></style>

在父组件A中使用这个组件:

父组件A.vue:
<template>
  <div class="wrapper">
    <el-statistic :value="output[0]" prefix="" />
    <div class="mt-1 title">本月销售总额</div>

    <!-- 引入子组件 -->
    <test></test>
  </div>
</template>

现在我在A组件的样式文件中,选择test组件中根元素div class="test",是可以选中的。

<style scoped lang="scss">
.wrapper {
  background-color: coral;

  .title {
    color: red;
  }
}

//test子组件
.test {
  color: blue;
}
</style>

在这里插入图片描述
能选中的原因是因为,test组件的根元素上存在着父组件Adata-v-d48692a9哈希值:
在这里插入图片描述
根据scoped样式机制,针对选择器.test,他选中的元素是在当前组件A.vue中的,同时也是目标元素,那么就给这个选择器加上了哈希值data-v-d48692a9,变成.test[data-v-d48692a9],这样正好可以选中。

如果我们的test组件中还有其它嵌套的DOM,我们还是这样选择,可以选中吗?

test.vue
<template>
  <div class="test">
    这里是test组件,是子组件
    <div class="test-inner">test内部</div>
  </div>
</template>
//A组件的style
<style scoped lang="scss">
.wrapper {
  background-color: coral;

  .title {
    color: red;
  }
}

.test {
  color: blue;

  .test-inner {
    font-size: 30px;
    color: green;
  }
}
</style>

这样是不能生效的,如图。
在这里插入图片描述
原因是因为:在这种父子嵌套的结构中,子组件是一个单根组件,那么这个子组件的根元素上就会带着父组件的哈希值,但是其内部的DOM并不会带上,如图:
在这里插入图片描述
这也就意味着,子组件的根元素是在渲染父组件中的,所以有父组件的哈希值,但是子组件内部的dom元素,是属于子组件
那么我们写的这个选择器,理论上是.test .test-inner[data-v-d48692a9],虽然.test-inner是目标元素,但他不是A.vue组件内部的元素,他没有data-v-d48692a9属性,vue也不会把data-v-d48692a9附加到.test-inner上。

这时候就轮到了:deep()登场了。
如果我们把A组件中的样式代码改为:

.test {
  color: blue;

  :deep(.test-inner) {
    font-size: 30px;
    color: green;
  }
}

效果如图
在这里插入图片描述
我们查看css选择器如下:

在这里插入图片描述
根据GPT的回答,和我自己的总结,
加上:deep()以后,用来表示当前样式应该跳过 scoped 的作用域限制,因此编译后其选择器部分不会附加 data-v-*,意味着不要编译为.test-inner[data-v-*]的形式,而是保留为.test-inner的形式。

然后vue的scoped样式机制是针对你的选择器,从左向右的添加data-v-*的,从左向右开始找,找到你的目标元素,同时也是当前组件的内部元素,就会添加这个data-v-*,因为这针对目标元素,所有只会有一个元素被添加这个哈希值。
比如.test :deep(.test-inner),deep的作用是告诉vue不给.test-inner添加哈希值,但是他是目标元素啊,不给他加就会给他的最近的祖先(猜的),同时还是当前组件内部的元素添加,这里就是.test元素,也就有了上面的编译结果。

那如果没有祖先呢,比如:

:deep(.test) {
  color: red;
}

实际编译后的css为[data-v-d48692a9] .test
首先.test是A组件内部的元素,也是目标元素,但是加上deep则是告诉vue不要给他加哈希值,这个选择器又没有父级,这时就会直接添加[data-v-d48692a9] 相当于选中所有的带有这个属性的元素。

deep的用途就是用来在父组件中修改子组件内部元素的样式,所以通常是用来修改组件库内部的样式的,针对我们自己的组件,直接在组件中修改样式就行了,基本用不到deep。

3. 使用el-statistic组件,并修改样式

组件代码:

<template>
  <div class="wrapper">
    <el-statistic :value="output[0]" prefix="" />
    <div class="mt-1 title">本月销售总额</div>
  </div>
</template>

<style scoped lang="scss">
.wrapper {
  background-color: lightgrey;
}
</style>

el-statistic现在就是一个组件,作为当前组件的子组件,被引入进来,现在我们的需求是将目前的样式:
在这里插入图片描述
修改为下面的样式:
在这里插入图片描述
假如直接添加类class="statistic",然后添加样式,实际是不生效的,如下:

 <el-statistic :value="output[0]" prefix="" class="statistic" />

<style scoped lang="scss">
.statistic {
  color: #fff;
}
</style>

查看元素:
在这里插入图片描述
可以看到符号和数字74811并不是statistic元素的直接文本,有其它盒子包裹了这个文本。当前的样式选中的元素是class=el-statistic statisticdiv。实际上我们需要选中的是这个子组件内部的元素:el-statistic__prefix内部的span元素,所有首先我们需要选中el-statistic__prefix元素,这个逻辑正好就是在父组件中选中子组件内部的元素,所以这里使用:deep()可以生效。

.el-statistic {
  color: green;

  :deep(.el-statistic__prefix) {
    color: blue;
  }

  :deep(.el-statistic__number) {
    color: red;
  }
}

在这里插入图片描述
在这里插入图片描述


http://www.kler.cn/a/505773.html

相关文章:

  • 内联变量(inline variables):在多个文件中共享全局常量
  • STM32 FreeRTOS移植
  • 算法竞赛(蓝桥杯)贪心算法1——数塔问题
  • HTTP1.0/1.1/2.0/3.0 的区别?
  • 集合帖:区间问题
  • Emacs 折腾日记(九)——elisp 数组与序列
  • Nginx 可观测性最佳实践
  • MySQL之DDL语言
  • 新版 MacOS 无法从 /usr/local/lib 加载动态链接库的解决办法
  • 算法每日双题精讲 —— 二分查找(二分查找,在排序数组中查找元素的第一个和最后一个位置)
  • Windows 蓝牙驱动开发-安装蓝牙设备
  • java 设计模式 工厂模式
  • JavaScript前端高效性能优化策略:防抖和节流的详细介绍
  • 【JavaWeb】JavaWeb入门之Tomcat详解
  • CNCF云原生计算基金会
  • Yolo 对象检测系列更新无止境,Ultralytics 发布 Yolov11 更快,更强
  • 0115java面经
  • 【Rust自学】12.7. 使用环境变量
  • SpringBoot开发——Spring Boot 自动化测试框架的高效运用
  • Java并发编程——线程池(基础,使用,拒绝策略,命名,提交方式,状态)
  • Mybatis-底层是如何解决sql注入增删改查操作--删除操作
  • VUE请求返回二进制文件流下载文件例子
  • doc、pdf转markdown
  • STM32H7通过CUBEMX初始化移植LWIP,DHCP建立RAW TCP服务器,不停发成功
  • Spring MVC复杂数据绑定-绑定集合
  • VUE3 + Ant Design Vue4 开发笔记