使用 React Fela 创建组件样式

React 中的风格在所有形状和尺寸中都有。在盒子之外,您可以通过className属性分配类或通过将物体分配给style属性分配 CSS 属性。在大多数情况下,它们都足够,但没有缺点。使classNames动态需要定义额外的类,而stiles,同时允许动态属性,仍然需要锅炉板代码,并且不允许您深入hover等假类属性。

Fela是用于处理JavaScript中的状态驱动式风格的框架非文档库,它具有高性能,并为您提供一些灵活性,以便您如何使用它,而您可以自行使用Fela,但 react-fela可为您的React.js应用提供React绑定。

开始的

要开始,我们需要在我们的项目中添加react-fela:

通过NPM

1$ npm install --save react-fela

或通过 Yarn

1$ yarn add react-fela

对于这篇文章,我们将直接从fela库中使用一些方法,但不要担心,react-fela包括这种依赖性,所以我们应该好好去。

返回者

正如我们所承诺的那样,我们将需要使用fela库的一部分,即createRenderercreateRenderer方法被用来创建一个渲染器,它将被传递给一个Provider组件,它将包装利用Fela的组件。

下面的所有示例都将包括我们需要让魔法发生的锅炉板代码。

使用生成的 CSS 类

最不复杂的Fela例子不是理想的,但确实有最少的锅炉板代码。

Fela的工作方式是,它需要你的风格,用原子类生成适当的CSS,并允许你抓住可以传递到任何组件的classNames属性的CSS类:

 1import React from "react";
 2import { render } from "react-dom";
 3
 4import { createRenderer } from "fela";
 5import { Provider } from "react-fela";
 6
 7const renderer = createRenderer();
 8
 9const rule = ({
10  backgroundColor = "#6db65b",
11  borderColor = "#efbb35",
12  padding
13}) => ({
14  backgroundColor: backgroundColor,
15  border: `10px solid ${borderColor}`,
16  color: "#fff",
17  fontWeight: "bold",
18  padding: `${padding}px`,
19  ":hover": {
20    cursor: "pointer",
21    filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"
22  }
23});
24
25const container = document.createElement("div");
26document.body.appendChild(container);
27render(
28  <Provider renderer={renderer}>
29    <div className={renderer.renderRule(rule, { padding: 100 })}>
30      Hover Over Me!
31    </div>
32  </Provider>,
33  container
34);

正如您在示例中所看到的,渲染器用于基于被传入的 CSS 属性的对象生成我们的 CSS 和类名称。

规则只是一个简单的匿名函数,该函数返回一个对象,包括我们所有的属性,包括可能已经传入的任何属性。

因为规则只是一个返回对象的函数,您可以扩展并添加额外的逻辑,而不是立即返回预期对象。

使用原始元素

虽然以前的方法足够好,但有时可以创建一个可以轻松地在整个项目中重复使用的新组件。

在这些情况下,我们可以利用FelaComponent原始组件来创建一个新的组件:

 1import React from "react";
 2import { render } from "react-dom";
 3
 4import { createRenderer } from "fela";
 5import { FelaComponent, Provider } from "react-fela";
 6
 7const renderer = createRenderer();
 8
 9const rule = ({
10  backgroundColor = "#6db65b",
11  borderColor = "#efbb35",
12  padding
13}) => ({
14  backgroundColor: backgroundColor,
15  border: `10px solid ${borderColor}`,
16  color: "#fff",
17  fontWeight: "bold",
18  padding: `${padding}px`,
19  ":hover": {
20    cursor: "pointer",
21    filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"
22  }
23});
24
25const PaddedContainer = ({
26  backgroundColor,
27  borderColor,
28  padding,
29  children
30}) => (
31  <FelaComponent
32    rule={rule}
33    backgroundColor={backgroundColor}
34    borderColor={borderColor}
35    padding={padding}
36  >
37    {children}
38  </FelaComponent>
39);
40
41const container = document.createElement("div");
42document.body.appendChild(container);
43render(
44  <Provider renderer={renderer}>
45    <PaddedContainer padding={100}>
46      Hover Over Me!
47    </PaddedContainer>
48  </Provider>,
49  container
50);

使用类似的规则,我们可以创建一个新的PaddedContainer组件,我们可以通过renderRule直接传递属性,而无需上传和分配类。

自己创建组件

使用原始元素来创建新组件没有什么不对劲,但你倾向于通过直接创建组件来获得比你更大的锅炉板:

 1import React from "react";
 2import { render } from "react-dom";
 3
 4import { createRenderer } from "fela";
 5import { createComponent, Provider } from "react-fela";
 6
 7const renderer = createRenderer();
 8
 9const rule = ({
10  backgroundColor,
11  borderColor,
12  padding
13}) => ({
14  backgroundColor: backgroundColor,
15  border: `10px solid ${borderColor}`,
16  color: "#fff",
17  fontWeight: "bold",
18  padding: `${padding}px`,
19  ":hover": {
20    cursor: "pointer",
21    filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"
22  }
23});
24
25const AnotherPaddedContainer = createComponent(rule);
26
27const container = document.createElement("div");
28document.body.appendChild(container);
29render(
30  <Provider renderer={renderer}>
31    <AnotherPaddedContainer padding={100}>Hover Over Me!</AnotherPaddedContainer>
32  </Provider>,
33  container
34);

更干净,像我们用原始组件的例子一样可重复使用!

结论

无论您采取哪种方法,利用反射-fela可以通过消除您必须写的锅炉板量来加速在 React 中动态设计组件所需的时间。

若要查看上面的代码样本,请转到 CodeSandbox

享受吧!

Published At
Categories with 技术
Tagged with
comments powered by Disqus