React组件-插槽

443 阅读2分钟

React实现插槽:

  1. 组件的children子元素;
    • 通过 children 实现的方案有一个潜在的弊端,就是难以精确获取传入的原生组件或元素。如果在传入的 children 中顺序或个数发生变化,或者传入的 children 中包含了一些不期望的元素,那么通过索引值来获取元素的方式就会出现问题。
    • 可以使用 React 提供的 React.Children 工具函数来处理传入的 children。该工具函数提供了一系列方法,可以方便地对 children 进行操作。
export class App extends Component {
  render() {
    const btn = <button>按钮2</button>

    return (
      <div>
        {/* 1.使用children实现插槽 */}
        <NavBar>
          <button>按钮</button>
          <h2>哈哈哈</h2>
          <i>斜体文本</i>
        </NavBar>
      </div>
    )
  }
}
//children
export class NavBar extends Component {
  render() {
    const { children } = this.props
    console.log(children)

    return (
      <div className='nav-bar'>
        <div className="left">{children[0]}</div>
        <div className="center">{children[1]}</div>
        <div className="right">{children[2]}</div>
      </div>
    )
  }
}

image.png 2. props属性传递React元素;


    {/* 2.使用props实现插槽 */}
    <NavBarTwo 
      leftSlot={btn}
      centerSlot={<h2>呵呵呵</h2>}
      rightSlot={<i>斜体2</i>}
    />
    
    //子
export class NavBarTwo extends Component {
  render() {
    const { leftSlot, centerSlot, rightSlot } = this.props

    return (
      <div className='nav-bar'>
        <div className="left">{leftSlot}</div>
        <div className="center">{centerSlot}</div>
        <div className="right">{rightSlot}</div>
      </div>
    )
  }
}

image.png

组件作用域插槽

  • 作用域插槽可以让子组件将自己的数据传递给父组件,而不仅仅是父组件向子组件传递数据。具体来说,父组件可以定义一个插槽,并在其中使用特殊的语法来声明插槽的数据和渲染逻辑。然后,子组件可以将数据传递给父组件,使得父组件可以根据这些数据动态地渲染出不同的内容。
export class App extends Component {
  constructor() {
    super()

    this.state = {
      titles: ["流行", "新款", "精选"],
      tabIndex: 0
    }
  }

  tabClick(tabIndex) {
    this.setState({ tabIndex })
  }

  getTabItem(item) {
    if (item === "流行") {
      return <span>{item}</span>
    } else if (item === "新款") {
      return <button>{item}</button>
    } else {
      return <i>{item}</i>
    }
  }

  render() {
    const { titles, tabIndex } = this.state

    return (
      <div className='app'>
        <TabControl 
          titles={titles} 
          tabClick={i => this.tabClick(i)}
          // itemType={item => <button>{item}</button>}
          itemType={item => this.getTabItem(item)}
        />
        <h1>{titles[tabIndex]}</h1>
      </div>
    )
  }
}
//子组件
export class TabControl extends Component {
  constructor() {
    super()

    this.state = {
      currentIndex: 0
    }
  }

  itemClick(index) {
    // 1.自己保存最新的index
    this.setState({ currentIndex: index })

    // 2.让父组件执行对应的函数
    this.props.tabClick(index)
  }

  render() {
    const { titles, itemType } = this.props
    const { currentIndex } = this.state

    return (
      <div className='tab-control'>
        {
          titles.map((item, index) => {
            return (
              <div 
                className={`item ${index === currentIndex?'active':''}`} 
                key={item}
                onClick={e => this.itemClick(index)}
              >
                {/* <span className='text'>{item}</span> */}
                {itemType(item)}
              </div>
            )
          })
        }
      </div>
    )
  }
}

image.png