[译]React核心概念10:组合vs继承

原文连接:reactjs.org/docs/compos…html

引言

React拥有功能强大的组合模式,咱们推荐使用组合而非继承来实现代码的复用。react

在本章中,咱们将要讨论几个React新手常常会遇到的关于继承的问题并展现咱们如何使用组合解决它们。安全

包含关系

某些组件不能预先知道它的子元素是怎样的,这对于相似于SideBar或Dialog这类容器组件来讲是十分常见的。bash

咱们推荐在使用这类组件时使用特殊的children prop直接将子元素渲染到输出。框架

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}
复制代码

这样其余组件就能直接经过嵌入JSX标签将任意子元素传递给它们。ide

function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>
    </FancyBorder>
  );
}
复制代码

在JSX标签<FancyBorder>的任意值都会经过children prop传递给FancyBorder组件。因此因为FancyBorder<div>中渲染了{props.children},因此被传递进来的元素最终都被渲染到页面上。ui

固然这种状况不太常见,但有时候组件中咱们须要几个“洞”来传入对应prop。在这种状况下咱们就须要自定义prop名而不是使用children了。this

function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}
复制代码

React元素<Contacts /><Chat />只是对象,因此你能够像传递其余数据同样经过prop传递它们。这种方法可能会让你决定很想其余框架的“插槽”,可是在React中经过props传递的参数是没有限制的。spa

特例关系

有些时候咱们须要某个组件称为区别于其余组件的特例,好比WelcomeDialog就是Dialog的一个特例。code

在React中这也可以经过组合来实现。特殊组件经过渲染普通组件并加上适当的逻辑就能够达到想要的效果。

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

function WelcomeDialog() {
  return (
    <Dialog
      title="Welcome"
      message="Thank you for visiting our spacecraft!" />
  );
}
复制代码

组合也适用于class组件:

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
      {props.children}
    </FancyBorder>
  );
}

class SignUpDialog extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.handleSignUp = this.handleSignUp.bind(this);
    this.state = {login: ''};
  }

  render() {
    return (
      <Dialog title="Mars Exploration Program"
              message="How should we refer to you?">
        <input value={this.state.login}
               onChange={this.handleChange} />
        <button onClick={this.handleSignUp}>
          Sign Me Up!
        </button>
      </Dialog>
    );
  }

  handleChange(e) {
    this.setState({login: e.target.value});
  }

  handleSignUp() {
    alert(`Welcome aboard, ${this.state.login}!`);
  }
}
复制代码

那么继承呢?

咱们使用了成千上万的组件来完成Facebook,但咱们没有发现使用继承能有更好实现效果的例子。

props和组合让你自由,显式且安全地定义你的组件。请记得能够接收任意的props(基本类型数据,React元素或者方法)。

若是你想要在组件间复用非UI行的方法,那咱们推荐把它提取成JavaScript模块,这样组件就能够import(引入)它而不是继承它。

相关文章
相关标签/搜索