如何正确转义样式化组件的 css 函数?
How to correctly escape css functions for styled components?
上下文:我想使用相同的 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}
`
(...)
expandWidth、expandHeight、bottomBorderColor等都是关键帧动画。我只需要知道如何编写这些函数并将它们传递给我想要的样式化组件而不会出现该错误。
已解决
正如@jsejcksn 所建议的,我必须将样式化的 div 放入组件的范围内。然后我让 css 函数明确地接受参数并进行一些语法更改,然后将所需的道具传递给它们。
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;
`
)
)
}
`
我认为您期望您的函数将被评估,但这不是插值期间发生的情况。就像下面的示例一样,您的函数只是在模板文字中被字符串化。
// 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 样式为两个不同的组件设置动画。动画取决于传递给 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}
`
(...)
expandWidth、expandHeight、bottomBorderColor等都是关键帧动画。我只需要知道如何编写这些函数并将它们传递给我想要的样式化组件而不会出现该错误。
已解决
正如@jsejcksn 所建议的,我必须将样式化的 div 放入组件的范围内。然后我让 css 函数明确地接受参数并进行一些语法更改,然后将所需的道具传递给它们。
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;
`
)
)
}
`
我认为您期望您的函数将被评估,但这不是插值期间发生的情况。就像下面的示例一样,您的函数只是在模板文字中被字符串化。
// 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>;
};