react
中的样式问题,一瞬间脑壳没反应上来好像还回答错了,有点尴尬水一篇文章记录一下。react
父子组件demo
中,实际效果与书写的样式不太同样。直接上代码描述问题:javascript
Parent.js
import React from 'react'; import Child from './Child' import './Parent.less' function Parent() { return ( <div className="parent"> <Child/> <div className='component'>parent</div> </div> ); } export default Parent;
Parent.less
.parent{ background-color: blue; .component{ color: white; } }
import React from 'react'; import './Child.less' function Child() { return ( <div className="child"> <div className='component'>Child</div> </div> ); } export default Child
Child.less
.child{ background-color: red; .component{ color: black; } }
大概看一下代码,是有一个Parent
的父组件,蓝底白字。还有一个Child
的子组件,红底黑字。
那么实际渲染出的样式是什么样子的呢。以下图:css
实际看到的效果确实蓝底白字与红底白字,为何与写的代码有出入呢。html
打开调试工具,看到子组件被渲染成一个<div class="component">Child</div>
可是样式却被父组件的样式给覆盖变成了白色,java
缘由:这是由于在w3c 规范中,CSS 始终是「全局的」。在传统的 web 开发中,最为头痛的莫过于处理 CSS 问题。由于全局性,明明定义了样式,但就是不生效,缘由多是被其余样式定义所强制覆盖。react
.parent .component
和.child .component
是父级覆盖子级?这就要涉及到浏览器渲染原理与css的浏览器解析原则则了webpack
CSSOM(CSS Object Model)
。DOM
和CSSOM
合并为渲染树(rendering tree)
将会被建立,表明一系列将被渲染的对象。布局layout
。浏览器使用一种流式处理的方法,只须要一次绘制操做就能够布局全部的元素。painting
。须要注意的是,以上五个步骤并不必定一次性顺序完成,好比DOM或CSSOM被修改时,亦或是哪一个过程会重复执行,这样才能计算出哪些像素须要在屏幕上进行从新渲染。而在实际状况中,JavaScript和CSS的某些操做每每会屡次修改DOM或者CSSOM。git
看一个例子:github
.nav h3 span {font-size: 16px;}
在咱们不知道规则的状况下,咱们是这样猜想的,按照常人的思惟从左到右。先是找到.nav
,而后向下匹配全部的h3
和span
标签。若是在向下匹配的过程当中,没有匹配上的则回溯到上一级继续匹配其余子叶结点。web
但实际上,CSS选择器读取顺序是从右到左浏览器
若是是这样的规定的话,仍是上面的例子就变成了,先找到全部的span
标签,而后找span
标签是h3
的,而后再延着h3
往上寻找,这时候发现一个选择器的类名为.nav
就把这个节点加入结果集;若是一直往上找直到html
标签都没找到的话,就放弃这条线,换到另外一个span
进行寻找。
那么来看咱们的这个Demo
中的结构
<div class="parent"> <div class="child"> <div class="component">Child</div> </div> <div class="component">parent</div> </div>
浏览器先找到.component
往上寻找,发现了.child .component
这时候渲染出样式为黑色,而后接着向上寻找发现了.parent .component
发现存在这个CSS规则,因此这时候颜色变成了白色
CSS Modules
方案。CSS Modules
?把CSS
划分模块,自动为类名后面生成一个hash值保证类名全局惟一。
CSS Modules
的使用create-react-app
建立项目,修改webpack.config.js
// parent.js import styles from './Parent.less' <div className={styles.parent}> <Child/> <div className={styles.component}> css modules parent </div> </div> //child.js import styles from './Child.less' <div className={styles.child}> <div className={styles.component}> css modules child </div> </div>
配置完成以后发现样式类名变成了hash值,这样即保证了类名的惟一不会存在覆盖的问题