父组件控制子组件样式的问题

父组件控制子组件样式的问题

老师您好,我一直对父组件控制子组件样式这块有点迷,之前问过一位助教,但我还是感觉他的回答我不是很理解,所以想再问一下。比如说header组件,我想自己控制msg图标离最右边的距离,在父组件中用在子组件中定义的类名进行样式控制,用了样式穿透,最后也没有效果。但是之前我们引入第三方的swiper组件的时候引用它swiper的时候就可以在父组件中定义.swiper-container 的样式,我在父组件中自定义header的样式就不行了,但有时候又可以,比如说div {color: #fff} 它就会把所有的div元素变为白色,求老师解答。附上nav和分类页下的header的代码

这是nav的代码
<template>
<Navbar class="header">
<div slot="middle">请输入搜索内容</div>
<i slot="right" class="iconfont icon-msg"></i>
</Navbar>
</template>
<script type="text/javascript">
import Navbar from '@/base/navbar';
export default {
data() {
return {

}
},
components: {
Navbar
}
}
</script>
<style type="text/css" scoped>
@import 'src/assets/scss/mixins';
.header {
&.navbar {
background: $header-bgc-translucent;
}
}

.icon-font {
font-size: $icon-font-size;
color: #fff;
} 
.header >>> .navbar-right {
margin-right: 20px;
} //没有效果
div {
color: #fff;
} //有效果

</style>
header的代码
<template>
<Navbar class="header">
<div slot="middle">请输入搜索内容</div>
<i slot="right" class="iconfont icon-msg"></i>
</Navbar>
</template>
<script type="text/javascript">
import Navbar from '@/base/navbar';
export default {
data() {
return {

}
},
components: {
Navbar
}
}
</script>
<style type="text/css" scoped>
@import 'src/assets/scss/mixins';
.header {
&.navbar {
background: $header-bgc-translucent;
}
}

.icon-font {
font-size: $icon-font-size;
color: #fff;
} 
.header >>> .navbar-right {
margin-right: 20px;
} //没有效果
div {
color: #fff;
} //有效果

</style>


正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

8回答
好帮手慕慕子 2019-05-15 09:34:10

你好,  首先老师刚举的例子是针对你说的“我自己测试的随便写个div标签然后给他们加上两个类名。。。”这里给出的解答 ,如下

http://img1.sycdn.imooc.com//climg/5cdb6b860001252707240157.jpg

另, 你这里的navbar类是在子组件中设置的样式。 header类是在父组件中设置的样式。子组件优先使用自己设置的样式。所以最后显示的背景颜色是白色。

在vue中, 单个组件中的样式覆盖和前面课程所学的css层叠的规则一样。 但是, 如果子组件中定义了scoped属性如果想要在父组件中控制子组件的样式需要使用样式穿刺

如果帮助到了你, 欢迎采纳!

祝学习愉快~~


  • 提问者 qq_那些荒废流年 #1
    为什么子组件优先使用自己的样式 这是啥原因呢老师
    2019-05-15 10:05:59
  • 提问者 qq_那些荒废流年 #2
    问了这么久我觉得最关键的地方就是为什么子组件和父组件给相同的元素定义了样式,子组件的优先级会高于父组件?您只告诉了我结论,没有告诉我为什么是这样
    2019-05-15 10:09:50
  • 同学你好, 因为在vue框架中,规定就是这样使用的。 抱歉老师没有完全理解同学的意思,给同学造成了困扰。 不过同学下次可以像这样直接描述想问的是什么哦,便于准确的定位与解决问题。 祝学习愉快~~
    2019-05-15 11:20:03
提问者 qq_那些荒废流年 2019-05-14 23:38:58

奥 是这样呀老师 那在vue中应该怎么确定这种样式覆盖的关系呢 是像您举的例子那样,虽然header的类定义在后面 但是它的样式是先声明的吗 因为在控制台中我没办法像看您举的例子这样看的这么直观 所以有些搞不明白

好帮手慕慕子 2019-05-14 23:33:02

同学你好, css样式的覆盖可以由样式书写的位置顺序决定

你前面如下图所说的,标签中class类名后面的类名会覆盖前面的类名设置的样式, 这种说法是不严谨的。例:

http://img1.sycdn.imooc.com//climg/5cdadcd70001427214620374.jpg

老师这里给同学举个简单的例子, 如下图标签中的class中的last在first后面。 但是style中书写样式的时候。 first在last后面, 所以fist设置的color属性覆盖了last设置的color属性。最终字体颜色为绿色。示例:

http://img1.sycdn.imooc.com//climg/5cdadd8b00011f2c11281232.jpg

同学可下去结合示例测试一下, 加深自己的理解。 也可以回顾一下以前的视频课程,复习一下CSS层叠和优先级。 在CSS选择的艺术这一阶段的第四章中有详细的讲解哦。http://class.imooc.com/course/752

示例:

http://img1.sycdn.imooc.com//climg/5cdadec8000151ee13881378.jpg

如果帮助到了你, 欢迎采纳!

祝学习愉快~~~



好帮手慕慕子 2019-05-14 22:10:11

同学你好, css中的覆盖原则不是根据标签名中写的类名先后顺序的,后面的类名不一定会覆盖在前面的样式。 你这里为父组件设置背景颜色为透明的红色, 子组件设置背景颜色为白色。子组件的background属性样式覆盖了父组件的background属性。所以最后显示的背景颜色为白色。 而且你的截图中头部背景确实为白色。 示例:

http://img1.sycdn.imooc.com//climg/5cdacb3e0001fce327080960.jpg

如果帮助到了你 ,欢迎采纳!

祝学习愉快~~~

  • 提问者 qq_那些荒废流年 #1
    老师您好,我自己测试的随便写个div标签然后给他们加上两个类名,发现就是后面的类名的样式会覆盖前面的类名啊老师。那您说的不一定是这样覆盖的那到底是通过什么来判断的呢?我学习喜欢知道原理,谢谢老师了
    2019-05-14 22:41:18
  • 你好,在上面回复了你的问题,可以看一下。
    2019-05-14 23:33:27
提问者 qq_那些荒废流年 2019-05-14 21:24:49

http://img1.sycdn.imooc.com//climg/5cdac0f80001ac1d13590621.jpg还有一个问题老师,就像截图中这样我在父组件中给div加了color green的样式,这里为什么能够控制子组件的div的color样式,就像控制台上显示的,我画圈的地方,子组件继承了父组件color:green的样式,我很奇怪,因为给style加了scoped属性后会给每一个组件动态地生成一个专属的data-v属性,这里这两个div专属的data-v属性都不同啊,为什么还可以实现样式的控制?

  • 你好, 因为data-v是vue解析的时候自动添加上的。虽然你圈起来的地方属性不同。 但是vue框架内部做了处理, 不影响你的样式设置。 所以可以实现样式的控制。祝学习愉快~~~~
    2019-05-15 12:02:36
  • 就是说哪怕data-v不一样,如果子组件和父组件都有div元素的话,也是可以进行样式设置的是吧老师?
    2019-05-15 12:05:40
  • 是的。 可以这样理解, 祝学习愉快~~~
    2019-05-15 13:14:07
提问者 qq_那些荒废流年 2019-05-14 20:49:49

http://img1.sycdn.imooc.com//climg/5cdab8380001dc5213660621.jpg老师您好,在这里我給header组件在父组件中设置了header类,子组件中本来设置的有navbar这个类,您说的父组件中设置与子组件相同的属性样式, 会被子组件覆盖。这句话我不是很理解,光看控制台的话,header类在navbar类的后面,按照css中的规则的话如果一个元素上设置了两个类的话,如果有样式冲突的话后面的类会覆盖掉前面的类,这里却没有按照这个规则来实现,这是为什么?

好帮手慕慕子 2019-05-14 10:44:06

同学你好, 可以这样理解

1、因为你在header组件中为div设置字体颜色为白色, 这个div是使用的slot插槽显示navBar中。且在navBar中没有为这里的div设置color属性。 导致字体颜色为白色。

可以尝试在子组件中为div设置color属性

http://img1.sycdn.imooc.com//climg/5cda28e90001883704040132.jpg

效果图:

http://img1.sycdn.imooc.com//climg/5cda2907000133b706120055.jpg

所以这就说明如果在组件中定义了scoped属性。 会优先使用自己组件内部设置的样式, 父组件中设置了相同的属性样式, 即使优先级高, 也会被子组件中的样式覆盖。

2、例如你这里在header组件中为图标设置右外边距, 但是没有效果, 因为在父组件的穿透样式写的不对 , 导致子组件中为图标设置了右外边距, 覆盖了父组件设置的样式。 

stylus的样式穿透 使用">>>"

sass和less的样式穿透 使用"/deep/"

因为这里使用的是sass, 所以推荐使用“/deep/” 进行穿透

http://img1.sycdn.imooc.com//climg/5cda48f90001b25704990197.jpg

效果图:

http://img1.sycdn.imooc.com//climg/5cda49e20001f5a209760088.jpg

3、 最后: 因为组件化的原因就是为了将整体的功能拆分开, 实现模块化管理,便于项目后期的维护, 所以推荐组件的样式设置在对应的组件中, 方便后期对相应的组件进行样式的调整。

如果帮助到了你, 欢迎采纳!

祝学习愉快~~~


  • 提问者 qq_那些荒废流年 #1
    不好意思老师 我搞错了 >>>是stylus中的语法 在scss样式穿透应该写成 /deep/ 这样就可以控制右边icon的margin-right了,老师我还是有点糊涂,为什么有时候控制子组件样式要用到样式穿透来控制,有时候不用也能控制。这有什么规律或者原理吗。麻烦老师总结一下
    2019-05-14 14:16:51
  • 1、 因为如果在子组件中定义了scoped属性。 会优先使用自己组件内部设置的样式,父组件中设置与子组件相同的属性样式, 会被子组件覆盖。 2、 如果在父组件中使用了样式穿透控制子组件的样式, 可以覆盖子组件的样式。 3、组件化就是为了实现模块化管理,便于项目后期的维护, 所以推荐组件的样式设置在对应的组件中, 方便后期对相应的组件进行样式的调整
    2019-05-14 17:27:00
  • 提问者 qq_那些荒废流年 #3
    关于样式穿透我看了看控制台,应该就是加重了父组件中样式的优先级,所以才可以穿透成功的吧老师? 另外关于第一点,我还有点疑问,麻烦您看下评论,我放个图
    2019-05-14 20:44:24
提问者 qq_那些荒废流年 2019-05-13 21:02:56
<template>
<div class="navbar">
<div class="navbar-left" v-if="$slots.left">
<slot name="left"></slot>
</div>
<div class="navbar-middle" v-if="$slots.middle">
<slot name="middle"></slot>
</div>
<div class="navbar-right" v-if="$slots.right">
<slot name="right"></slot>
</div>
<p v-text="text" v-if="text"></p>
</div>
</template>
<script type="text/javascript">
export default {
data() {
return {

}
},
props: {
text: {
type: String,
default: ""
}
},
}
</script>
<style scoped>
@import 'src/assets/scss/mixins';
.navbar {
height: 50px;
@include flex-between();
background: #fff;
}
.navbar-left {
margin-left: 5px;
}
.navbar-middle {
margin: 0 10px;
flex: 1;
}
.navbar-right {
margin-right: 5px;
}
p {
position: absolute;
top: 0;
bottom: 0;
left: 20%;
right: 20%;
@include flex-center();
// text-align: center;
// line-height: 50px;
//text-align 和 line-height 也能实现和flex-center相同的效果,只不过这是一个基础组件,因此不应该
//将line-height的高度定死
font-size: 15px;
}
</style>

这个是navbar的,抱歉,代码贴重复了

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
热门框架Vue开发WebApp 18版
  • 参与学习           人
  • 提交作业       209    份
  • 解答问题       3299    个

本路径是通过ES6基础知识、运用Zepto、Swiper、fullPag等移动端常用工具包、以及当下流行框架Vue,结合多个实战案例,还原真实开发场景,最终实现手机端购物商城网页开发。

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师