前言
单页应用开发中,所有组件的css最终会整合到一个html中,样式就容易出现冲突(两个组件有相同的类名,出现样式错误)。样式私有化在单页应用中是一个需要去解决的问题。
vue css样式私有化
做法:style上加入scoped即可。要覆盖第三方样式使用::v-deep即可
原理:
- 加上scoped之后,当前组件下的节点都会加上一个自定义的属性(这个唯一!!)。
- 当前组件的css选择器采用了属性选择器,属性就是上一步自定义的唯一的属性。
第三方组件无法覆盖的原因:
.van-tabs__line {
background: yellow;
}
在某一个组件里面,加了scoped,覆盖第三方ui库的样式(自己写的代码)
.van-tabs__line[data-v-7a7a37b1] {
background: yellow;
}
因为加了scoped,所以最终会编译成上诉的样子,有一个属性选择器
<div class="van-tabs__line" style="transform: translateX(51px) translateX(-50%);"></div>
很明显,你写的样式无法适配上诉节点
react css样式私有化
react并没有vue这一套机制,目前没有一个特定的方式。所以当前市面上流行的有如下几种,这几种各有优缺点,请根据实际应用场景进行选择。
行内样式
优点:
- 使用简单: 简单的以组件为中心来实现样式的添加
- 扩展方便,使用灵活: 通过使用对象进行样式设置,可以方便的扩展对象来扩展样式
- 避免冲突: 最终都编译为元素的行内样式,不存在样式冲突的问题
局限性,(不适合大型项目)
- 不能使用伪类: 这意味着 :hover、:focus、:actived、:visited 等都将无法使用
- 不能使用媒体查询: 媒体查询相关的属性不能使用
- 减低代码可读性: 如果使用很多的样式,代码的可读性将大大降低
- 没有代码提示: 当使用对象来定义样式时,是没有代码提示的
- js文件过大: css全写在了js中,导致js过大,js过大(白屏问题)
总结:
不是主流,一些情况下可以使用(你的一个div的背景图片是从后端来的)
样式表
CSS样式表应该是我们最常用的定义样式的方式!但多人协作开发中,很容易导致组件间的样式类名冲突,从而导致样式冲突;所以此时需要我们人为有意识的避免冲突!
具体做法
- 保证组件最外层的类名比较独特:路径名称-组件名称的方式
- 组件的其他样式以嵌套的方式写在最外成那个独特的类名之下
优点:
- 样式与js分离:(不会存在js比较大)
- 能使用所有css的功能
- 容易编写
缺点:
- 人为的规避,还是可能出现冲突
- 性能低:css选择器可能过长,性能低(css解析顺序是从右到左)
css-modules
原理:
CSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效;产生局部作用域的唯一方法,就是使用一个独一无二的class名字;这就是 CSS Modules 的做法!
创建module文件:xxx.module.css
.personal {
width: 300px;
height: 200px;
}
.personal span {
color: green;
}
.title {
color: red;
font-size: 16px;
}
.subTitle {
color: red;
font-size: 14px;
}
使用es6的方式导入及使用
import React from 'react';
import sty from './demo.module.css';
<div classname={sty.title}></div>
不经过编译的类名
:global(.fl) {
display: flex;
}
CSS Modules 允许使用 :global(.className) 的语法,声明一个全局规则。凡是这样声明的class,都不会被编译成哈希字符串。
继承(类似于sass中的mixin)
.title {
font-size: 20px;
color: pink;
}
.til {
composes: title;
border: 1px solid red;
}
composes类似于mixin(scss)
优点:
- 不需要人为去约束
缺点:
- 稍显麻烦
- 不能使用sass,less等高级语法
React-JSS
JSS: css in js(在js里面写css)
React-JSS 使用新的 Hooks API 将 JSS 与 React 结合使用。 使用步骤如下:
- 安装react-jss: yarn add react-jss
- 借助它的方法createUseStyles ,返回一个hook函数
- 执行hook函数,得到一个一个的类
const userStyle = createUseStyles({
box: {
width: '300px',
border: '1px solid red',
},
title: {
color: '#ff6900',
display: 'flex',
justifyContent: 'space-between',
'& span': {
'&:nth-child(1)': {
color: 'yellow'
}
}
}
})
export default function ChildJss() {
const { box, title } = userStyle()
return (
<div className={box}>
<p className={title}>
<span>我是</span>
<span>title</span>
</p>
</div>
)
}
优点
- 功能强大: 不仅支持css的所有东西,也能和js想结合
- 灵活: 样式可以根据传入的props生成
缺点:
-
只能在hook组件中使用
- 如果硬要在类组件中使用它,请使用函数组件将其包一层(高阶组件的使用)
styled-components
基本用法
-
安装
- yarn add styled-components
-
创建一个样式js文件,编写样式。基本语法如下:
import styled from 'styled-components' // 安装插件:vscode-styled-components export const ChildComWrapper = styled.div` .title { color: red; } .sub-title { color: ${props => { console.log(props) if(props.theme === 'gray') return 'gray' return 'green' }}; &:hover { color: red; } } ` 返回的是一个组件哟
-
在组件中使用
import React from 'react' import { ChildComWrapper } from './style' // style-component export default function ChildCom() { return ( <ChildComWrapper theme={'gray'}> <p className='title'>我是title</p> <p className='sub-title'>我是sub-title</p> </ChildComWrapper> ) }
扩展用法(抽取变量,抽取公共的组件)
-
创建一个公共样式文件
import styled from 'styled-components' export const NavWrapper = styled.ul` display: flex; color: #000; li { margin-right: 10px; list-style-type: none; &.active { color: red; } } ` -
需要的地方使用
import React from "react"; import { ChildComWrapper } from "./style"; import { NavWrapper } from '../../assets/common' // style-component export default function ChildCom() { return ( <> <ChildComWrapper theme={"gray"}> <p className="title">我是title</p> <p className="sub-title">我是sub-title</p> </ChildComWrapper> <NavWrapper> <li className="active">登录</li> <li>我的</li> <li>秒杀</li> </NavWrapper> </> ); }