React — 使用样式化组件传递 props
React — Passing props with styled-components
我刚刚在 styled-components
documentation 中看到以下内容是错误的,它会影响渲染时间。如果是这样,我该如何重构代码并使用所需的道具来创建动态样式?
提前致谢。
选项卡组件
import React from 'react'
import styled from 'styled-components'
const Tab = ({ onClick, isSelected, children }) => {
const TabWrapper = styled.li`
display: flex;
align-items: center;
justify-content: center;
padding: 100px;
margin: 1px;
font-size: 3em;
color: ${props => (isSelected ? `white` : `black`)};
background-color: ${props => (isSelected ? `black` : `#C4C4C4`)};
cursor: ${props => (isSelected ? 'default' : `pointer`)};
`
return <TabWrapper onClick={onClick}>{children}</TabWrapper>
}
export default Tab
考虑样式化组件文档给出了针对不同主题使用反应上下文 api [2] 的示例。
我相信文档所说的是您应该避免在渲染组件中包含您的样式:
这样做
const StyledWrapper = styled.div`
/* ... */
`
const Wrapper = ({ message }) => {
return <StyledWrapper>{message}</StyledWrapper>
}
取而代之
const Wrapper = ({ message }) => {
// WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!!
const StyledWrapper = styled.div`
/* ... */
`
return <StyledWrapper>{message}</StyledWrapper>
}
因为发生的事情是当组件的 Props 发生变化时,组件将重新渲染并且样式将重新生成。因此,将其分开是有意义的。
因此,如果您进一步阅读 根据道具进行调整 部分,他们会解释这一点:
const Button = styled.button`
/* Adapt the colours based on primary prop */
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// class X extends React.Component {
// ...
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
// }
这是有效的,因为当你在 class X 中使用 Button 组件时,它会知道 class X 的属性,而无需你告诉它任何东西。
对于您的情况,我认为解决方案很简单:
const TabWrapper = styled.li`
display: flex;
align-items: center;
justify-content: center;
padding: 100px;
margin: 1px;
font-size: 3em;
color: ${props => (props.isSelected ? `white` : `black`)};
background-color: ${props => (props.isSelected ? `black` : `#C4C4C4`)};
cursor: ${props => (props.isSelected ? 'default' : `pointer`)};
`;
const Tab = ({ onClick, isSelected, children }) => {
return <TabWrapper onClick={onClick}>{children}</TabWrapper>
}
const X = <Tab onClick={() => console.log('clicked')} isSelected>Some Children</Tab>
我还没有测试过这个,所以请随意尝试一下,让我知道它是否适合你或任何适合你的东西!
您可以使用 Typescript 传递参数,如下所示:
<StyledPaper open={open} />
...
const StyledPaper = styled(Paper)<{ open: boolean }>`
top: ${p => (p.open ? 0 : 100)}%;
`;
有关功能组件的更简单示例:
假设你有一个类似多边形的箭头,你需要其中 2 个指向不同的方向。所以可以通过 props
传递旋转值
<Arrow rotates='none'/>
<Arrow rotates='180deg'/>
然后在组件箭头中,你必须像普通组件一样将道具传递给样式组件,但在样式组件中你必须像道具一样使用它:
import React from 'react';
import styled from "@emotion/styled";
const ArrowStyled = styled.div`
background-color: rgba(255,255,255,0.9);
width: 24px;
height: 30px;
clip-path: polygon(56% 40%,40% 50%,55% 63%,55% 93%,0% 50%,56% 9%);
transform: rotate(${props => props.rotates});
`
const Arrow = ({rotates}) => {
return (
<ArrowStyled rotates={rotates}/>
);
}
export default Arrow;
如果您使用的是 Typescript,请在您的样式文件中创建一个界面!
否则,您将无法访问 CSS
中的道具
import styled from 'styled-components'
interface StyledLiProps{
selected: boolean
}
export const TabWrapper = styled.li`
// styles ...
color: ${props => (selected ? `white` : `black`)};
background-color: ${props => (selected ? `black` : `#C4C4C4`)};
`
并且不要忘记在 JSX
中声明您想要在 CSS 中使用的道具
interface TabProps{
text: string;
}
const Tab = ({ text }: TabProps) => {
//...
return <TabWrapper selected={isSelected} onClick={() => updateTab}>{text}</TabWrapper>
}
另一种方法是
const StyledDiv = styled.div.attrs((props: {color: string}) => props)`
width: 100%;
height: 100%;
background-color: ${(props) => props.color};
`
//...
render() {
return (
<StyledDiv color="black">content...</StyledDiv>
);
}
通过这种方式,就您要发送到样式化组件中的道具而言,您是类型安全的。 (用 Typescript 编码时很好)
正在导出 styled-component
Button
并在功能组件
中将scrollPosition
作为道具传递
PassingPropsToSyledComponent
import styledComponents from "styled-components";
export const Button = styledComponents.div`
position: ${ props => props.scrollPosition ? 'relative' : 'static' };
`;
export const PassingPropsToSyledComponent = ()=> {
return(
<Button scrollPosition={scrollPosition}>
Your Text Here
</Button>
)
}
我刚刚在 styled-components
documentation 中看到以下内容是错误的,它会影响渲染时间。如果是这样,我该如何重构代码并使用所需的道具来创建动态样式?
提前致谢。
选项卡组件
import React from 'react'
import styled from 'styled-components'
const Tab = ({ onClick, isSelected, children }) => {
const TabWrapper = styled.li`
display: flex;
align-items: center;
justify-content: center;
padding: 100px;
margin: 1px;
font-size: 3em;
color: ${props => (isSelected ? `white` : `black`)};
background-color: ${props => (isSelected ? `black` : `#C4C4C4`)};
cursor: ${props => (isSelected ? 'default' : `pointer`)};
`
return <TabWrapper onClick={onClick}>{children}</TabWrapper>
}
export default Tab
考虑样式化组件文档给出了针对不同主题使用反应上下文 api [2] 的示例。
我相信文档所说的是您应该避免在渲染组件中包含您的样式:
这样做
const StyledWrapper = styled.div`
/* ... */
`
const Wrapper = ({ message }) => {
return <StyledWrapper>{message}</StyledWrapper>
}
取而代之
const Wrapper = ({ message }) => {
// WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!!
const StyledWrapper = styled.div`
/* ... */
`
return <StyledWrapper>{message}</StyledWrapper>
}
因为发生的事情是当组件的 Props 发生变化时,组件将重新渲染并且样式将重新生成。因此,将其分开是有意义的。
因此,如果您进一步阅读 根据道具进行调整 部分,他们会解释这一点:
const Button = styled.button`
/* Adapt the colours based on primary prop */
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// class X extends React.Component {
// ...
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
// }
这是有效的,因为当你在 class X 中使用 Button 组件时,它会知道 class X 的属性,而无需你告诉它任何东西。
对于您的情况,我认为解决方案很简单:
const TabWrapper = styled.li`
display: flex;
align-items: center;
justify-content: center;
padding: 100px;
margin: 1px;
font-size: 3em;
color: ${props => (props.isSelected ? `white` : `black`)};
background-color: ${props => (props.isSelected ? `black` : `#C4C4C4`)};
cursor: ${props => (props.isSelected ? 'default' : `pointer`)};
`;
const Tab = ({ onClick, isSelected, children }) => {
return <TabWrapper onClick={onClick}>{children}</TabWrapper>
}
const X = <Tab onClick={() => console.log('clicked')} isSelected>Some Children</Tab>
我还没有测试过这个,所以请随意尝试一下,让我知道它是否适合你或任何适合你的东西!
您可以使用 Typescript 传递参数,如下所示:
<StyledPaper open={open} />
...
const StyledPaper = styled(Paper)<{ open: boolean }>`
top: ${p => (p.open ? 0 : 100)}%;
`;
有关功能组件的更简单示例:
假设你有一个类似多边形的箭头,你需要其中 2 个指向不同的方向。所以可以通过 props
传递旋转值 <Arrow rotates='none'/>
<Arrow rotates='180deg'/>
然后在组件箭头中,你必须像普通组件一样将道具传递给样式组件,但在样式组件中你必须像道具一样使用它:
import React from 'react';
import styled from "@emotion/styled";
const ArrowStyled = styled.div`
background-color: rgba(255,255,255,0.9);
width: 24px;
height: 30px;
clip-path: polygon(56% 40%,40% 50%,55% 63%,55% 93%,0% 50%,56% 9%);
transform: rotate(${props => props.rotates});
`
const Arrow = ({rotates}) => {
return (
<ArrowStyled rotates={rotates}/>
);
}
export default Arrow;
如果您使用的是 Typescript,请在您的样式文件中创建一个界面! 否则,您将无法访问 CSS
中的道具import styled from 'styled-components'
interface StyledLiProps{
selected: boolean
}
export const TabWrapper = styled.li`
// styles ...
color: ${props => (selected ? `white` : `black`)};
background-color: ${props => (selected ? `black` : `#C4C4C4`)};
`
并且不要忘记在 JSX
中声明您想要在 CSS 中使用的道具interface TabProps{
text: string;
}
const Tab = ({ text }: TabProps) => {
//...
return <TabWrapper selected={isSelected} onClick={() => updateTab}>{text}</TabWrapper>
}
另一种方法是
const StyledDiv = styled.div.attrs((props: {color: string}) => props)`
width: 100%;
height: 100%;
background-color: ${(props) => props.color};
`
//...
render() {
return (
<StyledDiv color="black">content...</StyledDiv>
);
}
通过这种方式,就您要发送到样式化组件中的道具而言,您是类型安全的。 (用 Typescript 编码时很好)
正在导出 styled-component
Button
并在功能组件
中将scrollPosition
作为道具传递
PassingPropsToSyledComponent
import styledComponents from "styled-components";
export const Button = styledComponents.div`
position: ${ props => props.scrollPosition ? 'relative' : 'static' };
`;
export const PassingPropsToSyledComponent = ()=> {
return(
<Button scrollPosition={scrollPosition}>
Your Text Here
</Button>
)
}