样式私有化
大约 4 分钟
样式私有化
单页应用开发中,所有组件的css最终会整合到一个html中,样式私有化在单页应用中是一个需要去解决的问题。
vue css样式私有化
vue中样式私有化十分简单,style上加入scoped即可。要覆盖第三方样式使用::v-deep即可,原理如下:
原理就是 属性选择器
第三方样式无法覆盖的原理,
react css样式私有化
react并没有vue这一套机制,目前没有一个特定的方式。所以当前市面上流行的有如下几种,这几种各有优缺点,请根据实际应用场景进行选择。
1. 行内样式【*】
优点:
- **使用简单:** 简单的以组件为中心来实现样式的添加
- **扩展方便:** 通过使用对象进行样式设置,可以方便的扩展对象来扩展样式
- **避免冲突:** 最终都编译为元素的行内样式,不存在样式冲突的问题
局限性,(不适合大型项目)
- 不能使用伪类: 这意味着 :hover、:focus、:actived、:visited 等都将无法使用
- 不能使用媒体查询: 媒体查询相关的属性不能使用
- 减低代码可读性: 如果使用很多的样式,代码的可读性将大大降低
- 没有代码提示: 当使用对象来定义样式时,是没有代码提示的
- js文件过大:css-in-js都会有此问题
2. 样式表【***】
CSS样式表应该是我们最常用的定义样式的方式!但多人协作开发中,很容易导致组件间的样式类名冲突,从而导致样式冲突;所以此时需要我们人为有意识的避免冲突!
具体做法如下:
- 保证组件最外层的类名比较独特:路径名称-组件名称的方式
- 组件的其他样式以嵌套的方式写在最外成那个独特的类名之下
优点:
- 样式与js分离:(不会存在js比较大)
- 能使用所有css的功能
- 容易编写
缺点:
- 人为的规避,还是容易出现冲突
- 性能低:选择器过长
3. Css-modules【**】
原理:CSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效;产生局部作用域的唯一方法,就是使用一个独一无二的class名字;这就是 CSS Modules 的做法!
不经过编译的类名
:global(.fl) {
display: flex;
}
CSS Modules 允许使用 :global(.className) 的语法,声明一个全局规则。凡是这样声明的class,都不会被编译成哈希字符串。
继承(类似于sass中的mixin)
.title {
font-size: 20px;
color: pink;
}
.til {
composes: title;
border: 1px solid red;
}
优点:
- 不需要人为去约束
缺点:
- 稍显麻烦
- 不能使用sass,less等高级语法
4. React-JSS【****】
React-JSS 使用新的 Hooks API 将 JSS 与 React 结合使用。 使用步骤如下:
- 安装react-jss: yarn add react-jss
- 借助它的方法createUseStyles ,返回一个hook函数
- 执行hook函数,得到一个一个的类
import React from 'react'
// import './SubChild.scss'
import {createUseStyles} from 'react-jss'
const useStyle = createUseStyles({
title: {
color: 'red',
fontSize: '24px',
fontWeight: 'bold'
},
subTitle: {
color: props => {
console.log(props)
if(props.theme === 'gray') return '#eee'
return 'red'
},
fontSize: '20px',
// 基于 & 实现后代选择
'& span': {
color: '#000'
},
'&:hover': {
color: 'yellow'
}
}
})
export default function SubChild() {
const { title, subTitle } = useStyle({
theme: 'gray'
})
return (
<div className="box">
<h1>SubCHild box 下的h1</h1>
<p className={title}>我是title</p>
<p className={subTitle}>我是 <span>subtitle</span> </p>
</div>
)
优点
- 功能强大: 不仅支持css的所有东西,也能和js想结合
- 灵活: 样式可以根据传入的props生成
缺点:
- 只能在hook组件中使用
- 如果硬要在类组件中使用它,请使用函数组件将其包一层(高阶组件的使用)
5. 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> </> ); }