首页 > 解决方案 > React - 将 SCSS“对象”作为属性传递

问题描述

我正在创建一个供个人使用的自定义组件库,并且我想使其可定制。我想在这里使用的方法类似于下面的代码。我不确定这是否是最好的方法,甚至是否可以以这种方式使用它。我很高兴有任何使代码看起来不错的建议。谢谢

组件.tsx

interface IProps {
  cssClass: any; <-- what type to put here?
}

export const SomeCustomComponent = (props: IProps) => {
  return (
    <>
      <div className={cssClass}>
        <p className={cssClass.header}>Header</p>
        <Icon className={cssClass.icon}/>
      </div>
    </>
  )
}

样式.scss

.myComponent {
  color: white;
  .header { margin-left: 10px; }
  .icon { margin-right: 10px; } 
}

主要组件.tsx

import styles from './Styles.scss'
const MainComponent = () => {
  return (
    <>
      <SomeCustomComponent cssClass={styles.myComponent}/>
    </>
  )
}

标签: reactjssass

解决方案


有多种方法可以实现定制样式,我想到了两种方法(以及经过一些研究的第三种方法)。还有其他方法可以做到这一点。前两个选项在没有 CSS-Modules 的情况下执行此操作。第三个是尝试使用 CSS-Modules 解决这个问题。

选项1

将样式从父组件传递给子组件。您可以styles在父级中动态更新并将其传递给子级。因为您将对象作为道具传递,所以这可能会导致不必要的重新渲染并损害性能。内联样式很好,因为它们很容易动态创建和作为道具传递。它们是传递动态样式的事实上的方式。

import React, { CSSProperties } from 'react';

interface CSSStyles {
  [key: string]: CSSProperties;
}

const MainComponent = () => {
  const styles: CSSStyles = {
    header: { marginLeft: "10px" }, // Dynamically update
    icon: { marginRight: "10px" }, // Dynamically update
    myComponent: { color: "black" }, // Dynamically update
  };

  return (
    <>
      <SomeCustomComponent cssClasses={styles} />
    </>
  );
};

interface Props {
  cssClasses: CSSStyles;
}
const SomeCustomComponent = ({ cssClasses }: Props) => {
  return (
    <div style={cssClasses.myComponent}>
      <p style={cssClasses.header}>Header</p>
      <Icon style={cssClasses.icon} />
    </div>
  );
};

选项 2

您可以将 aclassName作为字符串传递并在父级中更新它。这需要您在.scss文件中创建多个类。由于cssClasses道具在这里传递了一个对象,这也可能导致不必要的重新渲染。如果性能出现问题,您可以对此进行调整。

.tsx

interface CSSStyles {
  [key: string]: string;
}

const MainComponent = () => {
  const styles: CSSStyles = {
    header: "header", // Dynamically change
    icon: "icon", // Dynamically change
    myComponent: "myOtherComponent", // Dynamically change
  };

  return (
    <>
      <SomeCustomComponent cssClasses={styles} />
    </>
  );
};

interface Props {
  cssClasses: CSSStyles;
}
const SomeCustomComponent = ({ cssClasses }: Props) => {
  return (
    <div className={cssClasses.myComponent}>
      <p className={cssClasses.header}>Header</p>
      <Icon className={cssClasses.icon} />
    </div>
  );
};

.scss

.myComponent {
  color: white;
  .header {
    margin-left: 10px;
  }
  .icon {
    margin-right: 10px;
  }
}

.myOtherComponent {
  color: black;
  .header {
    margin-left: 100px;
  }
  .icon {
    margin-right: 100px;
  }
}

选项 3

一种 CSS 模块特定的方式。看起来你可以:

  • 将每个孩子包裹在一个 div 中
  • 将 className 作为 props 传递
  • 使用 CSS 子组合器
  • 创建多个 CSS 类并传递 className(类似于选项 2)。

这些似乎特定于 CSS-Modules,但似乎比选项 1 或 2 更复杂。我不确定 CSS-Modules 的性能影响。

有关参考,请参阅https://stackoverflow.com/a/55082008/9931154https://stackoverflow.com/a/34036086/9931154。CSS-Modules 文档似乎没有提到与您的问题有关的任何内容。


推荐阅读