构建 React 知识体系(十一) React 插槽slot

3,147 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

在 vue 的使用中,我们时常会使用插槽来解决已经有架子的情况,将组件代码插入,那么在 react 中如何实现插槽呢?

默认插槽

直接在父组件中插入组件信息,然后在子组件中获取,当使用的组件中间放入东西的时候就会自动的被props中children属性接收,这时我们就可以根据jsx语法的渲染特点来使用children实现插槽功能。

类组件的实现

父组件 - index.jsx


import React, { Component } from 'react';

import NavBar from './NavBar';

export default class App extends Component {
  render() {
    const leftJsx = <span>aaa</span>;
    return (
      <div>
        <NavBar name="" title="" className="">
          <span>aaa</span>  {/*将想要传入的组件放在组件中间*/}
          <strong>bbb</strong>
          <a href="/#">ccc</a>
        </NavBar>
      </div>
    )
  }
}

子组件 NavBar.jsx

import React, { Component } from 'react'

export default class NavBar extends Component {
  render() {
    // this.props.children; 通过props.children 可以打印出来看出组件的信息
    return (
      <div className="nav-item nav-bar">
        <div className="nav-left">
          {this.props.children[0]} {/* 预留的默认插槽 */}
        </div>
        <div className="nav-item nav-center">
          {this.props.children[1]}
        </div>
        <div className="nav-item nav-right">
          {this.props.children[2]}
        </div>
      </div>
    )
  }
}

函数组件

import React from 'react'

export default function App() {
  return (
    <div>
      {/* 在组件中传入想扩展的内容 */}
      <NavBar>
        <div>我被在使用的组件中展示了</div>
      </NavBar>
    </div>
  )
}


function NavBar(props) {
  // 接收children属性
  const { children } = props
  return (
    <div>
      <p>我是slot组件</p>
      {/* 使用 children属性进行占位,如果有内容就渲染传入的内容*/}
      {children}
    </div>
  )
}

具名插槽

将组件由一个props 值接受传值后然后在组件中接收,这样就可以让组件的名称获取,props.render是一种通过props进行传参的模式,并不是非要吧参数写为render,它可以是自己定义的任何字段名。

类组件

父组件 - index.jsx

import React, { Component } from 'react';

import NavBar from './NavBar';

export default class App extends Component {
  render() {
    const leftJsx = <span>aaa</span>;
    return (
      <div>
        <NavBar leftSlot={leftJsx}
                centerSlot={<strong>bbb</strong>}
                rightSlot={<a href="/#">ccc</a>}/>
      </div>
    )
  }
}

子组件 NavBar.jsx

import React, { Component } from 'react'

export default class NavBar extends Component {
  render() {
    const {leftSlot, centerSlot, rightSlot} = this.props;

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

函数组件

import React from 'react'

export default function Partent() {

  return (
    <div>
      {/* 在组件中传入自定义展示的内容 */}
      <NavBar leftSlot={leftJsx}
                centerSlot={<strong>bbb</strong>}
                rightSlot={<a href="/#">ccc</a>}/>
    <div/>
  )
}


function NavBar(props) {
  // 接收children属性
   const {leftSlot, centerSlot, rightSlot} = props;
  console.log(props, 'props---')

  return (
    <div>
      {/* 渲染自定义的组件 */}
      <div className="nav-item nav-bar">
        <div className="nav-left">
          {leftSlot}
        </div>
        <div className="nav-item nav-center">
          {centerSlot}
        </div>
        <div className="nav-item nav-right">
          {rightSlot}
        </div>
      </div>
  )
}

总结

优点: 如果是有一个子元素信息,可以直接使用,这样也省去很多定义的麻烦。

缺点: 如果是有多个组件呢,就可以很麻烦,因为你无法判断你想要的组件放在那个位置比较好,因为键值也是一个比较麻烦的问题。