当前位置: 代码网 > it编程>前端脚本>Vue.js > Vue中的scoped和 elememt-plus的样式修改方法

Vue中的scoped和 elememt-plus的样式修改方法

2025年02月13日 Vue.js 我要评论
1. style的scoped属性scoped属性是为了实现样式隔离,使得组件之间的样式互不影响。现在我们有组件a.vue<template> <div class="wrappe

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;
  }
}

到此这篇关于vue中的scoped和 elememt-plus的样式修改的文章就介绍到这了,更多相关vue scoped和 elememt-plus样式修改内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com