如何实现标签不可知风格的组件?
How to achieve tag agnostic styled components?
如果我想要一个按钮,但只是其中的展示部分,那么如果我这样做:
import styled from 'styled-components'
const Button = styled.button`
color: red;
text-align: center;
`
我不得不渲染一个 button
标签,但是如果语义上我需要一个锚点呢?
既然我们只是使用 JavaScript,为什么不使用函数呢?
const myButtonStyle = (styled, tag) => {
return styled[tag]`
color: red;
text-align: center;
`
}
const Button = myButtonStyle(styled, 'button')
您也可以将它与锚标签一起使用,没有什么能阻止您。
import styled from 'styled-components'
const Button = styled.a`
color: red;
text-align: center;
`
如果你想保留两者,可以通过将它们拉出来重复使用样式:
import styled from 'styled-components'
const styles = `
color: red;
text-align: center;
`
const Button = styled.button`
${styles}
`
const LinkButton = styled.a`
${styles}
`
我在 styled-components issue tracker 上问过同样的问题:https://github.com/styled-components/styled-components/issues/494
我找到的当前 "solution" 是:
// agnosticStyled.js
import React from 'react'
import styled from 'styled-components'
export default styled(
({tag = 'div', children, ...props}) =>
React.createElement(tag, props, children)
)
然后在您需要时:
import React from 'react'
import styled from './agnosticStyled'
const Button = styled`
color: palevioletred;
text-transform: uppercase;
`
export default Button
最后:
import React from 'react'
import Button from './Button'
const Component = () =>
<div>
<Button>button</Button>
<Button tag="button">button</Button>
<Button tag="a" href="https://google.com">button</Button>
</div>
export default Component
这是一个完整的功能示例:https://codesandbox.io/s/6881pjMLQ
styled-components 提供 withComponent
这对于您想要对组件使用不同标签的情况非常有用。这类似于@siddharthkp 在功能上的回答,但使用 API。
文档中的示例:
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// We're replacing the <button> tag with an <a> tag, but reuse all the same styles
const Link = Button.withComponent('a')
// Use .withComponent together with .extend to both change the tag and use additional styles
const TomatoLink = Link.extend`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<Link>Normal Link</Link>
<TomatoLink>Tomato Link</TomatoLink>
</div>
);
正如@typeoneerror 所指出的,styled-components 提供了WithComponent
。您可以使用它来基于包含标签的道具创建新组件。搭载示例,它看起来像这样:
const _Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const Button = ({ as: tag = 'button', children, ...props }) => {
// We're replacing the <button> tag with whatever tag is assigned to the 'as' prop (renamed to 'tag' and defaulted to button), but reuse all the same styles
const Composed = _Button.withComponent(tag);
// We return the newly-created component with all its props and children
return <Composed {...props}>{children}</Composed>;
};
render(
<div>
<Button>Normal Button</Button>
<Button as='a'>Normal Link</Button>
</div>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
copy/pasta 来自文档中的示例:
const Component = styled.div`
color: red;
`;
render(
<Component
as="button"
onClick={() => alert('It works!')}
>
Hello World!
</Component>
)
如果我想要一个按钮,但只是其中的展示部分,那么如果我这样做:
import styled from 'styled-components'
const Button = styled.button`
color: red;
text-align: center;
`
我不得不渲染一个 button
标签,但是如果语义上我需要一个锚点呢?
既然我们只是使用 JavaScript,为什么不使用函数呢?
const myButtonStyle = (styled, tag) => {
return styled[tag]`
color: red;
text-align: center;
`
}
const Button = myButtonStyle(styled, 'button')
您也可以将它与锚标签一起使用,没有什么能阻止您。
import styled from 'styled-components'
const Button = styled.a`
color: red;
text-align: center;
`
如果你想保留两者,可以通过将它们拉出来重复使用样式:
import styled from 'styled-components'
const styles = `
color: red;
text-align: center;
`
const Button = styled.button`
${styles}
`
const LinkButton = styled.a`
${styles}
`
我在 styled-components issue tracker 上问过同样的问题:https://github.com/styled-components/styled-components/issues/494
我找到的当前 "solution" 是:
// agnosticStyled.js
import React from 'react'
import styled from 'styled-components'
export default styled(
({tag = 'div', children, ...props}) =>
React.createElement(tag, props, children)
)
然后在您需要时:
import React from 'react'
import styled from './agnosticStyled'
const Button = styled`
color: palevioletred;
text-transform: uppercase;
`
export default Button
最后:
import React from 'react'
import Button from './Button'
const Component = () =>
<div>
<Button>button</Button>
<Button tag="button">button</Button>
<Button tag="a" href="https://google.com">button</Button>
</div>
export default Component
这是一个完整的功能示例:https://codesandbox.io/s/6881pjMLQ
styled-components 提供 withComponent
这对于您想要对组件使用不同标签的情况非常有用。这类似于@siddharthkp 在功能上的回答,但使用 API。
文档中的示例:
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// We're replacing the <button> tag with an <a> tag, but reuse all the same styles
const Link = Button.withComponent('a')
// Use .withComponent together with .extend to both change the tag and use additional styles
const TomatoLink = Link.extend`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<Link>Normal Link</Link>
<TomatoLink>Tomato Link</TomatoLink>
</div>
);
正如@typeoneerror 所指出的,styled-components 提供了WithComponent
。您可以使用它来基于包含标签的道具创建新组件。搭载示例,它看起来像这样:
const _Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const Button = ({ as: tag = 'button', children, ...props }) => {
// We're replacing the <button> tag with whatever tag is assigned to the 'as' prop (renamed to 'tag' and defaulted to button), but reuse all the same styles
const Composed = _Button.withComponent(tag);
// We return the newly-created component with all its props and children
return <Composed {...props}>{children}</Composed>;
};
render(
<div>
<Button>Normal Button</Button>
<Button as='a'>Normal Link</Button>
</div>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
copy/pasta 来自文档中的示例:
const Component = styled.div`
color: red;
`;
render(
<Component
as="button"
onClick={() => alert('It works!')}
>
Hello World!
</Component>
)