如何正确转义样式组件的 css 函数?

Posted

技术标签:

【中文标题】如何正确转义样式组件的 css 函数?【英文标题】:How to correctly escape css functions for styled components? 【发布时间】:2021-10-17 02:28:31 【问题描述】:

上下文:我想使用相同的 css 样式为两个不同的组件制作动画。动画依赖于传递给 AnimatedBox 组件的一些道具,例如,如果只有 props.right 为真,则仅对右边框进行动画处理。我认为css函数可以完成这项工作,所以为了不重复代码,我只创建元素并调用函数。但是,无论我做什么,我都会收到以下错误,并且组件的行为不符合预期:

Functions that are interpolated in css calls will be stringified.

这是我的一些代码(它被截断了)。

const AnimatedBox = props => (
    <>
        props.absolute
            ? 
            <MaskWrapper>
                <BeforeMask ...props/>
                <AfterMask ...props/>
            </MaskWrapper>
            :
            <AnimatedDiv ...props></AnimatedDiv>
    </>
)

export default AnimatedBox

const commonConfig = css`
    box-sizing: inherit;
    position: absolute;
    content: '';
    border: 1px solid transparent;
    border-radius: 3px;
`
const beforeConfig = css`
    top: 0;
    left: 0;
    border-top-color: $(top) => `$top && "#60d75a"`;
    border-right-color: $(right) => `$right && "#60d75a"`;
    animation: $expandWidth 0.25s ease-out forwards,
    $expandHeight 0.25s ease-out 0.25s forwards;
`
const afterConfig = css`
    right: 0;
    bottom: 0;
    animation: $(bottom, left) => `$
        (bottom && left) 
        ?
            `
                $bottomBorderColor 0s ease-out 0.5s forwards,
                $leftBorderColor 0s ease-out 0.5s forwards,
                $expandWidth 0.25s ease-out 0.5s forwards,
                $expandHeight 0.25s ease-out 0.75s forwards;
            `
        : (
            bottom 
            ?
                `   
                    $bottomBorderColor 0s ease-out 0.5s forwards,
                    $expandWidth 0.25s ease-out 0.5s forwards,
                    $expandHeight 0.25s ease-out 0.75s forwards;
                `
            : (
                left 
                &&
                    `
                        $leftBorderColor 0s ease-out 0.5s forwards,
                        $expandWidth 0.25s ease-out 0.5s forwards,
                        $expandHeight 0.25s ease-out 0.75s forwards;
                    `
                )
            )    
        `
    ;
`
const BeforeMask = styled.div`
    $beforeConfig
`
(...)

expandWidthexpandHeightbottomBorderColor等都是关键帧动画。我只需要知道如何编写这些函数并将它们传递给我想要的样式组件而不会出现该错误。

已解决

正如@jsejcksn 所建议的,我必须将样式化的 div 放入组件的范围内。然后我让 css 函数显式地接受参数并进行一些语法更改,然后将所需的 props 传递给它们。

const AnimatedBox = props => 
    (...)
    const BeforeMask = styled.div`
        $beforeConfig(props.top, props.right)
    `
    (...)

    return (
    <>
        props.absolute
            ? 
            <MaskWrapper>
                <BeforeMask ...props/>
                <AfterMask ...props/>
            </MaskWrapper>
            :
            <AnimatedDiv ...props></AnimatedDiv>
    </>
)

const beforeConfig = (top, right) => css`
    top: 0;
    left: 0;
    border-top-color: $top && "#60d75a";
    border-right-color: $right && "#60d75a";
    animation: $expandWidth 0.25s ease-out forwards,
    $expandHeight 0.25s ease-out 0.25s forwards;
`
const afterConfig = (bottom, left) => css`
    right: 0;
    bottom: 0;
    animation: $
        (bottom && left) 
        ?
        css`
            $bottomBorderColor 0s ease-out 0.5s forwards,
            $leftBorderColor 0s ease-out 0.5s forwards,
            $expandWidth 0.25s ease-out 0.5s forwards,
            $expandHeight 0.25s ease-out 0.75s forwards;
        `
        : 
        (
            bottom 
            ?
            css`  
                $bottomBorderColor 0s ease-out 0.5s forwards,
                $expandWidth 0.25s ease-out 0.5s forwards,
                $expandHeight 0.25s ease-out 0.75s forwards;
            `
            : 
            (
                left 
                &&
                css`
                    $leftBorderColor 0s ease-out 0.5s forwards,
                    $expandWidth 0.25s ease-out 0.5s forwards,
                    $expandHeight 0.25s ease-out 0.75s forwards;
                `
            )
        )    
    
`

【问题讨论】:

【参考方案1】:

我认为您期望您的函数将被评估,但这不是插值期间发生的情况。就像下面的示例一样,您的函数只是在模板文字中被字符串化。

// where is name defined?
const str = `hello $(name) => `$name`!`;
console.log(str); //=> "hello (name) => `$name`!"

您需要使用您期望能够使用的变量定义范围内的样式(例如,如果这些来自组件的道具,则在组件内部):

const name = 'Earth';

const str = `hello $name!`;
console.log(str); //=> "hello Earth!"
const Component = (props) => 
  const divStyle = css`
    background-color: $props.bgColor;
    color: white;
  `;

  const VariableColorDiv = styled.div`$divStyle`;

  return <VariableColorDiv>hello world</VariableColorDiv>;
;

【讨论】:

以上是关于如何正确转义样式组件的 css 函数?的主要内容,如果未能解决你的问题,请参考以下文章

less样式如何使用cssmodule

如何在 Angular 指令的 Link 函数中设置 CSS 样式

如何仅将 css 样式应用于特定的 Vue 组件及其子组件?

如何防止外部 CSS 覆盖 Web 组件样式

如何使用 CSS 模块在 React 中设置子组件的样式

我应该如何为样式化组件编写 Jest 测试用例并监视 css 以验证样式是不是正确?