文章目录
className怎么命名
我看网上推崇BEM的写法规范,但是个人认为其实很不好理解,建议类名的命名和功能或者业务结合最好,跟容易让人看懂。
class写法方案
在vue中想写具有作用域的css只需要在style标签加上scope
就可以,react需要怎么实现呢?我这里就记录几个自己使用过的方案。
普通引入写法(禁用!!!)
先提醒一个不推荐的引入方式。
例如
- Hone
- - a.jsx
- - a.css
然后在a,jsx中引入
import './a.css'
这样子写当以后项目越来越大的时候,会出现样式污染问题,十分的不推荐。
css module(最推荐)
用create-react-app创建项目的,只需要在你写的css文件上命名成xxx.module.css,然后引入到你的组件,引入的是一个对象。具体写法直接百度一下哈哈哈哈。
原理大致是例如有个类名为box
,他给你写入标签中是文件名称_box_哈希值
css in js(很强,但逐步被弃用)
如上面说的,个人觉得其实在一般情况下的开发中,全局css和css module一起用基本就够用了,但看到网上都比较推崇css in js的解决方案,所以个人也来学习一下。
简单来讲就是把css用js去表达出来,有更高的扩展性和自定义性,目前网上已经有很多成熟的库了,这里就记录一下比较轻量的一种方案—emotion库。
安装
代码来源慕课网
首先要安装相对应的库:
yarn add @emotion/react @emotion/styled // 核心库
yarn add @emotion/core // 可以在内联样式中写伪类
然后我使用的是vscode,所以可以装一个插件让其写css in js的时候能够高亮代码,vscode-styled-components。
简单使用
在内联样式中
/** @jsx jsx */
import { jsx } from '@emotion/react' // 上面的必须写上哦,如果不起作用试试换成/* @jsxImportSource @emotion/react */
render(
<div
css={{
backgroundColor: 'red',
'&:hover': {
color: 'blue'
}
}}
>
123
</div>
)
正常使用:
import styled from '@emotion/styled'
return (
<Container>
</Container>
);
const Container = styled.div` // 就是把div换成带有下面样式的组件Container,Container是自定义名称
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
`
如果要加样式的标签是第三方库的话,例如antd的Card组件:
import styled from '@emotion/styled'
return (
<ShadowCard>
</ShadowCard>
);
const ShadowCard = styled(Card)` // 用括号括起来就行了
width: 100%;
`;
样式组件
除了普通的写法,我们还可以专门封装成一个带有可自定义样式的公共样式组件去使用,例如我们做一个Row排版组件:Row.tsx
import styled from "@emotion/styled"
const Row = styled.div<{
gap?: number | boolean;
justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
marginBottom?: number;
}>`
display: flex;
align-items: center;
justify-content: ${(props) => (props.justifyContent? props.justifyContent : 'space-between')};
margin-bottom: ${(props) => props.marginBottom ? (props.marginBottom + "rem") : 0};
> * {
margin-top: 0 !important;
margin-bottom: 0 !important;
margin-right: ${(props) =>
typeof props.gap === "number"
? props.gap + "rem"
: props.gap
? "2rem"
: undefined};
}
`;
export default Row
除了一些固定样式,我们还可以设置props去自定义一些属性,那么怎么去使用呢:
import Row from "components/Row";
return (
<Header>
</Header>
);
const Header = styled(Row)`
padding: 3.2rem;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.1);
z-index: 1;
`;
原理
其实就是把你写的css自动去生成一个类名,然后添加到指定的元素上
写法上的原理:
function fn(a){
console.log(a);
}
fn('1')
fn`1 2`
个人建议
个人认为一般项目中使用css module已经能满足95%以上的需求了,且css in js把css都写到js里去了,js代码量变多了,编译成本也就高,也更不易读。但如果真要是遇到那种需要灵活控制样式的再考虑这个也可以。
最新消息,许多开发团队逐步把这个淘汰了,听说是运行时性能成本远远超过了开发体验的提升。
另外推荐的库 Styled-components,写法都差不多风格,但对TS支持比较友好,没有新增的标签属性,而emotion使用的时候有新增的属性,如果用了TS,TS会不认识这些属性。
动态className方案(推荐)
主要是解决某个标签中的className动态变化的情况,让jsx代码不必过多三元表达式,增加易读性。
利用classnames库,直接上例子:
import classNames from 'classnames'
const ComponentList: FC = ()=> {
let btnClass = classNames({
btn: true,
'btn-pressed': isPressed,
'btn-over': isOver
});
return <button className={btnClass}>按钮</button>;
}
}
通过上面的函数可以将btnClass生成'btn btn-pressed btn-over'
等组合。
如果结合了css modules写法:
const a= styles['component-wrapper']
const b= styles.selected
const wrapperClassName = classNames({
[a]: true,
[b]: true,
})
是不是比一堆三元表达式好多了?所以还是很推荐的!
类似的库还有clsx(这个是next.js推荐的):https://www.npmjs.com/package/clsx
style写法方案
一般情况下不推崇直接在标签上写style。
个人认为:
- 优先级太高
- 增加jsx的代码量
- 性能差
当然,一些场景确实适合直接写style,例如一些非常简单的调整。
下面介绍几个stlye的其他写法。
style对象写法
这种方法比较死,而生效的优先级太高了,特定场景下使用吧:
import React, { Component } from 'react';
const Styles = {
close: {
position: 'fixed',
top: '10px',
right: '10px'
}
};
export default class Modal extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<>
<div style={Styles.close}>
</div>
</>
)
}
}
jsx写法
组要是借助 Styled-jsx 这个第三方库,就是在jsx中写style,但是不太推荐,听说对ts支持不是特别好(因为有拓展的标签属性,ts不知道这些属性是啥)。
SVG组件
react给我们提供了使用svg图片的组件(这个真的很容易忽略的):
import { ReactComponent as SoftwareLogo } from "assets/software-logo.svg"; // 以组件的形式引入svg图片,并另命名为SoftwareLogo
return (
<SoftwareLogo width={"18rem"} color={"rgb(38, 132, 255)"} />
)