【问题标题】:Safe/Efficient to use string.replace() with styled components?将 string.replace() 与样式化组件一起使用是否安全/有效?
【发布时间】:2020-01-20 13:05:28
【问题描述】:

创建一个类似于以下内容的函数是否安全有效:

style = {
   border: '1px solid primary'
}

并将其转换为:

style = {
   border: '1px solid rgb(0, 0, 0)'
}

在将其作为道具提供给如下样式组件之前?

const StyledContainer = styled.div`
  border: ${props => props.border};
`;

我担心它会随着时间的推移而变慢,因为我需要每次迭代每个样式对象并在每个项目上使用类似 string.replace() 的东西。我也担心 CSS 注入并且不熟悉它们。我这样说是因为我的项目中有很多文本输入字段。


为了澄清,我确实有它的工作:

const replaceStringWithTheme = (string, theme) => {
  const modifiedString = string
    .replace("primary", theme.primary)
    .replace("secondary", theme.secondary)
    .replace("background", theme.background)
    .replace("xs", "0.5rem")
    .replace("sm", "1rem")
    .replace("md", "1.5rem")
    .replace("lg", "2.0rem")
    .replace("xl", "2.5rem");
  return modifiedString;
};

const replacePropsWithTheme = (props, theme) => {
  const cloneObject = { ...props };
  for (let [key, prop] of Object.entries(cloneObject)) {
    if (typeof prop === "string") {
      cloneObject[key] = replaceStringWithTheme(prop, theme);
    }
  }
  return cloneObject;
};

export function Container(props) {
  const theme = useThemeState();
  const modProps = replacePropsWithTheme(props, theme);
  return <StyledContainer {...modProps}>{props.children}</StyledContainer>;
}

const StyledContainer = styled.div`
  width: ${props => props.width};
  height: ${props => props.height};
  margin: ${props => props.margin};
  padding: ${props => props.padding};
  background: ${props => props.background};
  border: ${props => props.border};
`;

我只是想知道,这真的是个坏主意吗?我正在克隆通过的道具。由于某种原因,似乎可以通过更改默认的 props 对象来间接执行一些任意代码。

【问题讨论】:

  • 你让用户输入样式吗?
  • 我只让他们选择主题颜色,例如色轮上的主要或次要颜色。我担心我克隆了传递给组件的道具对象并迭代每个属性。我不认为代码会以不同的方式执行,但我不确定。

标签: javascript css reactjs styled-components


【解决方案1】:

我可以想出两种方法来做你想做的事。

1.) 使用基本样式。

const baseStyle = {
    position: 'absolute',
    color: 'red',
    // other properties
}

然后使用它,但只更改要更改的内容。

const inheritedStye = {
    ...baseStyle,
    color: 'green'
}

2.) 使用样式创建器功能

const createStyle = (color = 'primary', width = '1px', type = 'solid') => {
  return {
     border: `${widht} ${type} ${color}`
  }
}

// use it like
const myStyle = createStyle('rgb(0,0,0)')

如果有什么我遗漏的,请告诉我。

【讨论】:

  • 我认为这也可以通过执行以下操作来完成:${props => props.color || '红色'}
  • @AdamJohnston 有多种方法可以做同样的事情。我的回答更多地针对如何重用您的样式。我的想法是,我们可以只询问需要什么并得到它,而不是到处更换。我知道遗留代码会带来复杂性,但如果我们要替换道具中的字符串,代码只会变得复杂。如果将来你想要别的东西怎么办?
  • 我同意;如果其他人看到您的答案并希望以更简洁的方式(嗯,第一部分),我只是添加评论。我实际上让它工作得很好,而且我不那么担心,因为我将“样式”对象传递给每个组件而不是一般的道具。主要优点是在组件的底部,我可以有类似“border: 1s solid primary”的东西,一旦作为道具传递,它就会转换为主题间距和主题颜色。据我所知,性能没有受到影响,尽管我没有渲染太多 CSS 重组件。
【解决方案2】:

给出你所要求的,我认为你可以很容易地用道具做到这一点

const Box = styled.div`
  color: ${props => props.primary ? "red" : "blue"};
`;

或者你实际上可以在其中完成整个功能

const Box = styled.div`
  color: ${props => {
    switch (props.colorStyle) {
      case "primary": return "red";
      case "secondary": return "blue";
      default: return "black";
    }
  }};
`;

然后你就可以通过这个来使用它了

<Box colorStyle="primary">I'm with primary color</Box>

【讨论】:

  • 这行得通……但这不是我想要的。我喜欢能够通过类似 {border: 'sm solid primary'} 的想法。它帮助我快速扩展和构建。你拥有它的方式就是我使用它的方式。
猜你喜欢
  • 2017-09-19
  • 2018-03-17
  • 2012-07-26
  • 2021-01-15
  • 1970-01-01
  • 2020-01-19
  • 1970-01-01
  • 2019-09-01
  • 2018-10-17
相关资源
最近更新 更多