组合还是继承?

作者: 莫铭 | 来源:发表于2017-04-29 15:42 被阅读92次

React具有强大的组合模型,我们推荐使用组合来代替继承,这样可以在组件间重用代码。
在本节中,我们将考虑几个问题,遇到这些问题时,刚接触React的开发者一般会考虑使用继承,而我们将展示如何用组合来解决他们。

包含

一些组件提前不知道它的孩子。在诸如侧栏和对话框这些通用“框”中尤为常见。
我们建议这种组件使用专门的childrenprop来直接传递子元素到他们的输出:

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>
  );
}

在CodePen上试一试
<FancyBorder>JSX标签中的所有东西都会作为childrenprop传递给FancyBorder组件。FancyBorder<div>中渲染{props.children},因此传入的元素将出现在最终输出中。
虽然这比较少见,但有时你还是会需要在组件中放置多个“槽位”。在这种情况下,你可以使用自己习惯来,来代替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 />
      } />
  );
}

在CodePen上试一试
诸如<Contacts /><Chat />的React元素也是对象,所以你可以像其他数据一样作为props传递。

特殊化

有时你我们认为一些组件是其他组件的“特殊情况”。比如,我们说WelcomeDialogDialog的特例。
在React中,这也可以通过组合来完成:通过props配置一个相对“通用的”组件,来渲染出一个相对“特殊的”组件:

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!" />
  );
}

在CodePen上试一试
组合对于定义成类的组件同样好使:

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}!`);
  }
}

在CodePen上试一试

那继承咋样?

在Facebook,我们在数千个组件中使用React,尚未发现有什么组件,需要我们推荐你使用继承去实现。
Props和组合提供了足够的灵活度,使得你能够以明确且安全的方法来自定义组件的外观和行为。
如果你想在组件间复用非界面功能,我们建议将它抽取到单独的JavaScript模块。组件可以导入它,然后使用需要的函数,对象或类,而不必扩展(继承)它。

相关文章

  • 组合还是继承?

    React具有强大的组合模型,我们推荐使用组合来代替继承,这样可以在组件间重用代码。在本节中,我们将考虑几个问题,...

  • 继承

    原型继承 借用构造函数 组合继承 原型式继承 寄生式继承 寄生组合继承 优点: 因为组合继承最大的问题是无论什么...

  • 二、js继承的几种方式及优缺点

    1、继承:原型链、借用构造函数、组合继承、原型式继承、寄生式继承、寄生组合继承

  • 组合继承,寄生组合继承,class继承

    组合继承 说明:核心是在子类的构造函数中通过 Parent.call(this) 继承父类的属性,然后改变子类的原...

  • JS继承方式总结 (转)

    借用构造函数继承 原型链式继承(借用原型链实现继承) 组合式继承 组合式继承优化1 组合式继承优化2 ES6中继承...

  • js继承方式

    类式继承 构造函数继承 组合继承 类式继承 + 构造函数继承 原型式继承 寄生式继承 寄生组合式继承 寄生式继承 ...

  • js之继承

    文章主讲 JS 继承,包括原型链继承、构造函数继承、组合继承、寄生组合继承、原型式继承、 ES6 继承,以及 多继...

  • javaScript 实现继承方式

    JavaScript实现继承共6种方式:原型链继承、借用构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合式继承。

  • ES5和ES6 实现继承方式

    在ES5 中:通过原型链实现继承的,常见的继承方式是组合继承和寄生组合继承;在ES6中:通过Class来继承 组合...

  • (九)

    寄生组合式继承前面说过,组合继承是JavaScript最常用的继承模式;不过,它也有自己的不足。组合继承最大的问题...

网友评论

    本文标题:组合还是继承?

    本文链接:https://www.haomeiwen.com/subject/ecmzzttx.html