demo-style:react styles 和 css in js 样式方案
1. 代码仓库
2. 主线任务
2.1. react 官方基础用法
css方案
// App.tsx
import './App.css';
export default function App() {
return <div className={'css_style'}></div>;
}
// App.css
.css_style{ display:flex }
2.2. Module.css
create-react-app和Vite中默认支持:
1、module 的方式 css 文件必须要加 .module
// App.tsx
import globalStyle from './global.module.css';
export default function App() {
return <div className={globalStyle.flex}>1</div>
}
// global.module.css
.flex{ display:flex }
2、module 方案的css name 会自动生成 hash 值
2.3. styled-components
styled-components是一个流行的 CSS-in-JS ****库,用于在 React(或其他框架)中以组件化的方式编写和管理 CSS 样式。它通过将样式直接嵌入 JavaScript/TypeScript 代码,解决了传统 CSS 的全局污染、命名冲突、动态样式难维护等问题
1、依赖下载:
pnpm add styled-components -S
2、ts 项目类型声明:
pnpm add @types/styled-components -D
3、App.tsx:
import styled from 'styled-components';
interface StyleButtonProps {
bg?: boolean;
}
// styled.* 范围(html元素,或者组件)
const StyleButton = styled.button<StyleButtonProps>`
color: #fff;
border: 0;
background: ${(props) => (props.bg ? '#000' : '#666')};
`;
export default function App() {
// 这里直接绑定 bg 会被渲染到 button dom 上 但是button没有这个属性 react会抛出警告 Warning: Received `true` for a non-boolean attribute `bg`
return <StyleButton bg={true}>3</StyleButton>;
}
4、自动生成hash值:
2.3.1. 解决渲染不是元素属性的警告
button 按钮没有 bg 这个属性,会抛警告
1、第一种解决办法 属性前面加 $ 告知 styled-components 这是仅用于样式的属性,不传递到 DOM
import styled from "styled-components";
interface StyleButtonProps {
$bg?: boolean;
}
// styled.* 范围(html元素,或者组件)
const StyleButton = styled.button<StyleButtonProps>`
color: #fff;
border: 0;
background: ${props => props.$bg ? "#000" : "#666"};
`
export default function App() {
return (<StyleButton $bg={true}>111</StyleButton>)
}
2、过滤属性(使用 shouldForwardProp)
import styled from "styled-components";
interface StyleButtonProps {
bg?: boolean;
}
const StyleButton = styled.button.withConfig({
shouldForwardProp: (prop) => !['bg'].includes(prop) // 过滤 bg 属性
})<StyleButtonProps>`
color: #fff;
border: 0;
background: ${(props) => (props.bg ? "#000" : "#666")};
`
export default function Home() {
return (<StyleButton bg>111</StyleButton>)
}
2.4. @vanilla-extract/css
@vanilla-extract/css是一个用于在 JavaScript 或 TypeScript 项目中编写 CSS 的工具包,它采用了 CSS-in-JS 的思想,但与传统的 CSS-in-JS 库(如 styled-components、emotion 等)有所不同。@vanilla-extract是基于构建时的 CSS 解决方案,它在构建阶段将样式代码编译成普通的 CSS 文件,避免了运行时的性能开销,同时还保留了 JavaScript 的灵活性和类型安全
@vanilla-extract/css 的主题方案在:www.yuque.com/chuxin-cs/c…
1、依赖下载
pnpm add @vanilla-extract/css -S
pnpm add @vanilla-extract/vite-plugin -D
2、Vite 中使用:
import {defineConfig} from 'vite'
import react from '@vitejs/plugin-react'
import {vanillaExtractPlugin} from '@vanilla-extract/vite-plugin'
export default defineConfig({
plugins: [
react(),
vanillaExtractPlugin()
],
})
3、基础用法:style.css.ts 注意如果是ts项目需要加 .ts 后缀,js项目就加.js
// style.css.ts
import { style } from '@vanilla-extract/css';
export const containerStyle = style({
padding: 20,
backgroundColor: '#fff',
vars: {
'--primary-color': '#007bff',
},
});
export const buttonStyle = style([
containerStyle, // 继承样式
{
color: 'white',
backgroundColor: 'var(--primary-color)',
':hover': {
opacity: 0.8,
},
},
]);
4、App.tsx 中:
import { containerStyle, buttonStyle } from './styles.css.ts';
export default function App() {
return (
<div className={containerStyle}>
<button className={buttonStyle}>点击我</button>
</div>
);
}
5、hash 值
2.4.1. globalstyle 设置全局样式
import { globalStyle } from '@vanilla-extract/css';
globalStyle('html, body', {
margin: 0
});
转换输出:
html, body {
margin: 0;
}
3. 支线任务
3.1. clsx
合并 css 类名
pnpm add clsx -S
1、App.tsx:
import clsx from "clsx";
export defaultfunction App(){
const className = clsx({
btn: true,
'btn-active': true,
'btn-error': true
})
// 最终dom结果:<div class="btn btn-error btn-active"></div>
return (
<div className={ className }></div>
)
}
2、效果
3.1.1. css modules 与 clsx 结合
import clsx from 'clsx';
import globalStyle from './global.module.css';
function App() {
const mergeClassName = clsx({
btn: true,
'btn-active': true,
'btn-error': true,
});
// css module 和 clsx 结合
const mergeClassNameModule = clsx(mergeClassName, {
// global.module.css 中的 flex 编译成 _btn_wyasb_1 这种hash规则 这是 module.css 自带的功能
[globalStyle.flex]: true,
});
return <div className={mergeClassNameModule}>6</div>
}
效果:
3.2. classnames
合并 CSS 类名
1、依赖下载
pnpm add classnames -S
2、App.tsx
import classNames from 'classnames'
export default function App(){
// classNames
const names = classNames('foo', 'bar'); // => 'foo bar'
// 动态
const key = 'classKey';
const names1 = classNames({ [key]: true }); // => 'classKey'
const names2 = classNames(names1,names)
return <div className={names2}></div> //最终结果:<div class="classKey foo bar"></div>
}
3、效果