什麼是 All in js
前段時間在別人的項目上了解到了styled-components插件,它能夠用js來寫css,方便的在其中加上需要的邏輯。React本身用過jsx已經把html用js來寫了,再加上styled-components,就能夠實現All in js 這種編碼方式。
如何看待All in js
瞭解之後跟小夥伴在羣裏討論了一下,這種All in js的方式比較有爭議,不僅在我們的討論中,在整個前端社區裏也是如此。部分人認爲“能用js來做的,必將用js來做”,而且確實在css中直接寫js邏輯有吸引人的地方。另一方面像我這種剛瞭解的人,認爲他上手不夠平滑,寫起來費勁,同時其實大部分css是不需要邏輯的。在與其他人的討論中也發現了一些其他缺點,比如增加了不少成本,新手不夠友好、全局樣式覆蓋成本高漲、僞類處理複雜、與AntD等組件庫結合有坑等。
與此同時 Sass/Less 社區也在飛速發展,尤其是 Stylelint 的成熟,可以通過技術約束的手段來避免 CSS 的 Bad Parts。所以在掘金看到的一篇文章中也號召大家迴歸 Sass/Less ,可見社區也逐漸拋棄了All in js的做法。但作爲一種極客範兒的嘗試,淺嘗輒止的去了解一下還是有點意思的,這裏就簡單放一些我嘗試過的代碼。
styled-components用例
這裏使用styled-components來寫了個環形圖表組件,來展示百分比數據
import React, { PureComponent } from "react";
import styled from "styled-components";
import PropTypes from "prop-types";
// CircleComponment組件的html結構
const CircleComponment = ({ className, precent }) => (
<div className={className}>
<div className="precent" />
<div className="text">
<strong>{precent}</strong>
<span>%</span>
</div>
</div>
);
// 使用styled-components的styled方法來給CircleComponment組件增加樣式後生成一個新的Circle組件
// 由於要使用css動態表現百分比,所以這裏的css是需要一些邏輯和計算的,很適合使用styled-components來做
// 但可以看到的是,也寫了很多不需要邏輯的純css,都混到一起之後,顯得很長,對閱讀不利。
const Circle = styled(CircleComponment)`
width: 110px;
height: 110px;
float: left;
position: relative;
line-height: 100px;
text-align: center;
margin: 0 20px;
&::before {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 10px solid #999;
border-radius: 50%;
z-index: 1;
}
&::after {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 10px solid #38fcc2;
border-radius: 50%;
clip: rect(0, auto, auto, 50px);
z-index: 2;
}
.precent {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 10px solid
${props => {
const precent = props.precent;
let color = "";
if (precent >= 0 && precent <= 50) {
color = "#999";
} else if (precent > 50 && precent <= 100) {
color = "#38fcc2";
}
return color;
}};
transform: rotate(
${props => {
const precent = props.precent;
let deg = 0;
if (precent >= 0 && precent <= 50) {
deg = precent * 3.6;
} else if (precent > 50 && precent <= 100) {
deg = (precent - 50) * 3.6;
}
return `${deg}deg`;
}}
);
border-radius: 50%;
clip: rect(0, auto, auto, 50px);
z-index: 3;
}
.text {
color: rgba(255, 255, 255, 1);
font-size: 30px;
font-family: Futura-Medium;
line-height: 110px;
}
`;
/**
* CircleGraph用於環形圖表
*/
export default class CircleGraph extends PureComponent {
static propTypes = {
precent: PropTypes.string, // 百分比數值
};
render() {
const { precent } = this.props;
return <Circle precent={precent} />;
}
}
// 使用時
<CircleGraph precent="30" />