React核心概念:组合vs继承

21 篇文章 0 订阅
21 篇文章 1 订阅

上一节:状态提升
下一节:以React的方式思考

React核心概念:组合vs继承

引言

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

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

包含关系

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

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

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

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

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},所以被传递进来的元素最终都被渲染到页面上。

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

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传递的参数是没有限制的。

特例关系

有些时候我们需要某个组件称为区别于其他组件的特例,比如WelcomeDialog就是Dialog的一个特例。

在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(引入)它而不是继承它。

上一节:状态提升
下一节:以React的方式思考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值