传统CSS使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 <!DOCTYPE html> <html lang="en"> <head> <style> #app{ color:red } </style> </head> <body> <div id="app">App</div> </body> </html>
在后来 style 标签被提取到一个 css文件里
React应用的CSS
index.html
1 2 3 4 5 6 7 <!DOCTYPE html> <html lang="en"> <head> </head> <body> <div id="root"></div> </body> </html>
styles.css
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 import React from "react"; import ReactDOM from "react-dom"; // 引入样式 import "./styles.css"; function App() { // react建议 class属性 使用 className 如果你不加可能依然可以运行。 建议就是按照react的建议做,不要自己作死。 return <div className="App">Hello World</div>; } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
这个代码好不好呢?
在一开始没什么问题,但是当你的组件逐渐变多,你就觉得不好
1 2 3 比如组件嵌套的情况下 都有一个 class="title" 它们之间就会相互影响
styles.css
1 2 3 4 5 .title { color: red; border: 1px solid red; padding: 10px; }
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; function Father() { return ( <div className="title"> 父亲组件 <Sun /> </div> ); } function Sun() { return ( <div> <div className="title">儿子组件</div> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<Father />, rootElement);
两个组件都有title样式 我只想让 字体颜色变红
唯一的办法就是给所有的组件加上一个前缀
如
1 2 .father-title{ ... } .sun-title{ ... }
这个方式叫做—— BEM命名法(思路就是加前缀)
为了防止各个组件之间的冲突,我们采用了加前缀的方式解决
styles.css
1 2 3 4 5 6 7 8 9 10 11 .father-title { color: red; border: 1px solid red; padding: 10px; } .sun-title { color: green; border: 1px solid green; padding: 10px; }
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; function Father() { return ( <div className="father-title"> 父亲组件 <Sun /> </div> ); } function Sun() { return ( <div> <div className="sun-title">儿子组件</div> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<Father />, rootElement);
如果你想动态设置主题 theme
1 2 3 4 5 6 7 8 function Sun(props) { const theme = props.theme; return ( <div> <div className=`sun-title sun-${theme}`>儿子组件</div> </div> ); }
有没有一种方式让我写多个 class更加的简单一点?
styles.css
1 2 3 4 5 6 7 8 9 10 11 12 .App { font-family: sans-serif; text-align: center; } .red { color: red; } .border10 { border: 10px solid red; }
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import React from "react"; import ReactDOM from "react-dom"; import classNames from "classnames"; import "./styles.css"; function App() { return ( <div className="App"> <h1 className={classNames("red", "border10")}>Hello CodeSandbox</h1> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
强迫症的心理(处女座)——模块化
每个组件对应一个目录 对应自己的css
1 2 3 4 5 6 7 8 |src --|topBar ----|topBar.css ----|topBar.js --|x ----|x.css ----|x.js --|index.js
强迫症的执念——我就不想用前缀
两个title 自己分开
css:做不到
前端:css go die !
既然你css做不到那你就靠边站,我用js
CSS in JS 简单来说这个方案大概有20种
google 搜索 github css in js
你会搜到一个仓库 css-in-js
里面收录了所有 css in js 的方案 那么有多少呢?
大概 60多种,开不开心有60多种
此时有一个问题,为什么做前端架构很难呢?
有没有什么在前端一开始觉得很NB到后面变得很垃圾
grunt 三年前 三年后
angular 1.x
如何区分这些库呢?
筛选css in js 的方案
styled-components
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import React from "react"; import ReactDOM from "react-dom"; import styled from "styled-components"; import "./styles.css"; const Button = styled.button` border-radius: 3px; border: 1px solid #666; color: #333; margin: 0 1em; padding: 0.25em 1em; `; function App() { return ( <div className="App"> <Button>按钮</Button> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
在线代码
这样就解决了,你写前缀就浑身难受的心态
强迫症是前端的原始动力
而且你的世界从此没有了 .css文件
在写一个topbar.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import React from "react"; import styled from "styled-components"; export default function Topbar(props) { const theme = props.theme; // 'white | black' const onClick = () => { console.log(1); }; const Logo = styled.div` width: 40px; height: 40px; background: grey; `; const Nav = styled.nav` height: 30px; background: #333; width: 200px; color: white; margin-left: 10px; `; const Wrapper = styled.div` display: flex; align-items: center; border: 1px solid black; padding: 10px; background: ${theme}; `; return ( <Wrapper> <Logo>logo</Logo> <Nav>nav</Nav> </Wrapper> ); }
此时你发现违背了 多年来前端的思想 内容样式分离
又回到解放前了
react 说 我不仅内容混在一起 行为也要混在一起
styled-components
目前react css比较火的方案
可以再也看不到css文件
不需要定义class
而且从工程角度来说——这个方案对新人非常好,不会因为你改一个样式造成整个项目瘫痪了,你只需要关心自己的组件
emotion方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 /** @jsx jsx */ import React from "react"; import { jsx } from "@emotion/core"; export default function X(props) { const theme = props.theme; return ( <div css={{ display: "flex", alignItems: "center", background: theme, padding: 10 }} > <div css={{ display: "inline-block", color: "red", fontSize: 20, white: 40, height: 40, background: "grey" }} > logo </div> <nav css={{ width: 200, height: 30, background: "#333", marginLeft: 10 }} /> </div> ); }
有个坑就是第一行必须写那个注释
根据与 直接 style=”color:red;” 没区别
强烈不推荐用
react-css-modules
我放弃了——为什么webpack还活着
如果你成功了,你就可以这样写样式了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import React from 'react'; import CSSModules from 'react-css-modules'; import styles from './table.css'; class Table extends React.Component { render () { return <div styleName='table'> <div styleName='row'> <div styleName='cell'>A0</div> <div styleName='cell'>B0</div> </div> </div>; } } export default CSSModules(Table, styles);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import Radium from 'radium'; import React from 'react'; import color from 'color'; class Button extends React.Component { static propTypes = { kind: PropTypes.oneOf(['primary', 'warning']).isRequired }; render() { // Radium extends the style attribute to accept an array. It will merge // the styles in order. We use this feature here to apply the primary // or warning styles depending on the value of the `kind` prop. Since its // all just JavaScript, you can use whatever logic you want to decide which // styles are applied (props, state, context, etc). return ( <button style={[ styles.base, styles[this.props.kind] ]}> {this.props.children} </button> ); } } Button = Radium(Button); // You can create your style objects dynamically or share them for // every instance of the component. var styles = { base: { color: '#fff', // Adding interactive state couldn't be easier! Add a special key to your // style object (:hover, :focus, :active, or @media) with the additional rules. ':hover': { background: color('#0074d9').lighten(0.2).hexString() } }, primary: { background: '#0074D9' }, warning: { background: '#FF4136' } };
总结四个CSS in JS 方案 1 2 3 4 5 6 7 8 9 10 11 1. styled-componends const Title = styled.div` 样式代码...` 2. emotion <div css={对象}> 3. css-module <div styleName="title"> 保证title不对其他组件有影响 4. radium <div style={[style.title,style.base]}>
如果是我我觉得第三个可能是最好的!
回顾
避免 同名 .title 冲突 加前缀
不想加前缀,强迫症
css in js 得到 60多个方案
按照star 选了 4个 来实现不写前缀
建议
1 2 3 4 5 6 7 8 9 10 11 12 13 如果写一个应用 app - 用 css-module - 或者 styled-componends 因为它们还是在写 css 如果写一个 UI库 lib - 使用旧的 css 方案 加前缀 - 因为上面的方式会生成随机名字,你的组件样式就没法被覆盖了 .title --> title_xd0031 这个名字是随机的,没法覆盖 .x-title --> .x-title 不帮你生成名字,可以进行改写和覆盖样式