• 使用高阶组件来改变样式
    • 例子: Carousel
    • 使用高阶组件
    • 用法

    使用高阶组件来改变样式

    有时有一些组件可能只需要很少的一部分state来维护一些很简单的交互, 我们也有充足的理由把这些组件作为可复用的组件.

    例子. Carousel组件的交互

    这个高阶组件会持有当前幻灯片的index并且提供前进和回退的功能.

    1. // 高阶组件
    2. import React from 'react'
    3. // 这个高阶组件其实可以被命名的更加通俗易懂, 比如Counter或者Cycle
    4. const CarouselContainer = (Comp) => {
    5. class Carousel extends React.Component {
    6. constructor() {
    7. super();
    8. this.state = {
    9. index: 0
    10. };
    11. this.previous = () => {
    12. const { index } = this.state;
    13. if (index > 0) {
    14. this.setState({index: index - 1})
    15. }
    16. };
    17. this.next = () => {
    18. const { index } = this.state;
    19. this.setState({index: index + 1})
    20. }
    21. }
    22. render() {
    23. return (
    24. <Comp
    25. {...this.props}
    26. {...this.state}
    27. previous={this.previous}
    28. next={this.next}/>
    29. )
    30. }
    31. }
    32. return Carousel
    33. };
    34. export default CarouselContainer;

    使用高阶组件

    1. // 纯UI component
    2. const Carousel = ({ index, ...props }) => {
    3. const length = props.length || props.children.length || 0;
    4. const sx = {
    5. root: {
    6. overflow: 'hidden'
    7. },
    8. inner: {
    9. whiteSpace: 'nowrap',
    10. height: '100%',
    11. transition: 'transform .2s ease-out',
    12. transform: `translateX(${index % length * -100}%)`
    13. },
    14. child: {
    15. display: 'inline-block',
    16. verticalAlign: 'middle',
    17. whiteSpace: 'normal',
    18. outline: '1px solid red',
    19. width: '100%',
    20. height: '100%'
    21. }
    22. };
    23. const children = React.Children.map(props.children, (child, i) => {
    24. return (
    25. <div style={sx.child}>
    26. {child}
    27. </div>
    28. )
    29. });
    30. return (
    31. <div style={sx.root}>
    32. <div style={sx.inner}>
    33. {children}
    34. </div>
    35. </div>
    36. )
    37. };
    38. // 最后的Carousel组件
    39. const HeroCarousel = (props) => {
    40. return (
    41. <div>
    42. <Carousel index={props.index}>
    43. <div>Slide one</div>
    44. <div>Slide two</div>
    45. <div>Slide three</div>
    46. </Carousel>
    47. <Button
    48. onClick={props.previous}
    49. children='Previous'/>
    50. <Button
    51. onClick={props.next}
    52. children='Next'/>
    53. </div>
    54. )
    55. };
    56. // 我们通过在外面包裹一层container组件来给这个组件带来更多的功能.
    57. export default CarouselContainer(HeroCarousel)

    通过保持样式和交互状态的分离, 基于同一个carsousel组件, 我们可以创造任意数量不同的更复杂的carousel组件,

    用法

    1. const Carousel = () => (
    2. <div>
    3. <HeroCarousel />
    4. </div>
    5. );