父组件传递子组件

传递元素内容

如果给自定义组件传递元素内容,则React会将元素内容作为children属性传递过去

todo…

子组件是 class 组件

  1. 第一种方式:直接在 constructor 中使用 this.props = props 的方式通信;

    import React, { Component } from 'react';
    
    // 1.类子组件
    class ChildCpn1 extends Component {
      constructor(props) {
        super();
        this.props = props;
      }
    
      render() {
        const { name, age, height } = this.props;
    
        return (
          <div>
            <h2>我是class的组件</h2>
            <p>展示父组件传递过来的数据: {name + " " + age + " " + height}</p>
          </div>
        )
      }
    }
    
    export default class App extends Component {
      render() {
        return (
          <div>
            <ChildCpn1 name="why" age="18" height="1.88" />
          </div>
        )
      }
    }
    
  2. 第二种方式:可以调用 super(props) 的方式通信

    1. 先看一下 Component 的源码,就知道为什么可以这样通信了
    function Component(props, context, updater) {
      this.props = props;
      this.context = context;
      // If a component has string refs, we will assign a different object later.
      this.refs = emptyObject;
      // We initialize the default updater but the real one gets injected by the
      // renderer.
      this.updater = updater || ReactNoopUpdateQueue;
    }
    
    1. 所以可以书写成这样:
    constructor(props) {
      super(props);
    }
    
  3. 第三种方式:省略构造函数,如果不指定构造方法,则使用默认构造函数:

    1. 对于基类,默认构造函数是:
    constructor() {}
    
    1. 对于派生类,默认构造函数是:
    constructor(...args) {
      super(...args);
    }
    

子组件是 function 组件

  1. 子组件是 function 组件,直接解构 props 即可:

    function ChildCpn2(props) {
      const { name, age, height } = props;
    
      return (
        <div>
          <h2>我是function的组件</h2>
          <p>展示父组件传递过来的数据: {name + " " + age + " " + height}</p>
        </div>
      );
    }
    
    export default class App extends Component {
      render() {
        return (
          <div>
            <ChildCpn2 name="kobe" age="30" height="1.98" />
          </div>
        );
      }
    }
    
  2. functional 组件 相对来说比较简单,因为不需要有构造方法,也不需要有 this 的问题;

子组件传递父组件

  1. 某些情况,子组件也需要向父组件传递消息:

    1. vue 中是通过自定义事件来完成的;
    2. React 中同样是通过 props 传递消息,只是让父组件给子组件传递一个回调函数,在子组件中调用这个函数即可;
  2. 计数器案例:

    import React, { Component } from 'react';
    
    // 子组件
    function CounterButton(props) {
      const { operator, btnClick } = props;
      // 将按钮封装到子组件中,发生点击事件,将内容传递到父组件中
      return <button onClick={btnClick}>{operator}</button>
    }
    
    export default class App extends Component {
      constructor(props) {
        super(props);
    
        this.state = {
          counter: 0
        }
      }
    
      changeCounter(count) {
        this.setState({
          counter: this.state.counter + count
        })
      }
    
      render() {
        return (
          <div>
            <h2>当前计数: {this.state.counter}</h2>
            <CounterButton operator="+1" btnClick={e => this.changeCounter(1)} />
            <CounterButton operator="-1" btnClick={e => this.changeCounter(-1)} />
          </div>
        )
      }
    }
    

组件通信案例

JavaScript
JavaScript
JavaScript
CSS
// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./style.css";

import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));
// App.js
import React, { Component } from "react";

import TabControl from "./TabControl";

export default class App extends Component {
  constructor(props) {
    super(props);

    this.titles = ["流行", "新款", "精选"];

    this.state = {
      currentTitle: "流行",
    };
  }

  itemClick(index) {
    this.setState({
      currentTitle: this.titles[index],
    });
  }

  render() {
    return (
      <div>
        <TabControl titles={this.titles} clickTitle={(index) => this.itemClick(index)} />
        <h2>{this.state.currentTitle}</h2>
      </div>
    );
  }
}
// TabControl.js
import React, { Component } from "react";

export default class TabControl extends Component {
  constructor(props) {
    super(props);

    this.state = {
      currentIndex: 0,
    };
  }

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

    return (
      <div className="tab-control">
        {titles.map((item, index) => {
          return (
            <div className="tab-item" onClick={(e) => this.itemClick(index)}>
              <span
                className={"title " + (index === currentIndex ? "active" : "")}
              >
                {item}
              </span>
            </div>
          );
        })}
      </div>
    );
  }

  itemClick(index) {
    this.setState({
      currentIndex: index,
    });
    this.props.clickTitle(index);
  }
}
.tab-control {
    height: 40px;
    line-height: 40px;
    display: flex;
}

.tab-control .tab-item {
    flex: 1;
    text-align: center;
}

.tab-control .title {
    padding: 3px 5px;
}

.tab-control .title.active {
    color: red;
    border-bottom: 3px solid red;
}

React 插槽

  1. Vue 插槽固定的做法是通过 slot 来完成;

  2. React 插槽有 children、props 两种方案可以实现,非常灵活;

children 实现

  1. 每个组件都可以获取到 props.children,它包含组件的开始标签和结束标签之间的内容;

  2. props.children 的源码实现:

    1. 如果只有一个元素,那么 children 指向该元素;
    2. 如果有多个元素,那么 children 指向的是数组,数组中包含多个元素;
  3. 示例代码:

    import React, { Component } from 'react';
    
    class NavBar extends Component {
      render() {
        return (
          <div className="nav-bar">
            <div className="item left">{this.props.children[0]}</div>
            <div className="item center">{this.props.children[1]}</div>
            <div className="item right">{this.props.children[2]}</div>
          </div>
        )
      }
    }
    
    export default class App extends Component {
      render() {
        return (
          <div>
            <NavBar>
              <div>返回</div>
              <div>购物街</div>
              <div>更多</div>
            </NavBar>
          </div>
        )
      }
    }
    

props 实现 (推荐)

  1. 通过 children 实现的方案虽然可行,但是有一个弊端:通过索引值获取传入的元素很容易出错,不能精准的获取传入的原生;

  2. 另外一个种方案就是使用 props 实现,通过具体的属性名,可以在传入和获取时更加的精准;

    import React, { Component } from 'react';
    
    class NavBar extends Component {
      render() {
        const { leftSlot, centerSlot, rightSlot } = this.props;
    
        return (
          <div className="nav-bar">
            <div className="item left">{leftSlot}</div>
            <div className="item center">{centerSlot}</div>
            <div className="item right">{rightSlot}</div>
          </div>
        )
      }
    }
    
    export default class App extends Component {
      render() {
        const navLeft = <div>返回</div>;
        const navCenter = <div>购物街</div>;
        const navRight = <div>更多</div>;
    
        return (
          <div>
            <NavBar leftSlot={navLeft} centerSlot={navCenter} rightSlot={navRight} />
          </div>
        )
      }
    }
    
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 父组件传递子组件
    1. 1.1. 传递元素内容
    2. 1.2. 子组件是 class 组件
    3. 1.3. 子组件是 function 组件
  2. 2. 子组件传递父组件
  3. 3. 组件通信案例
  4. 4. React 插槽
    1. 4.1. children 实现
    2. 4.2. props 实现 (推荐)