Reactjs入门官方文档(十)【composition-vs-inheritance】

此文章是翻译composition vs inheritance这篇React(版本v15.5.4)官方文档。

组合和继承

React 有一个非常强大的组合模式(composition model),在组件之间,我们建议使用组合(composition)而不是继承(inheritance)。

在这个部分,我们将会考虑几个对React 开发新手来说经常遇到的几个继承问题,展示我们如何使用组合方式来解决它们。

包含

一些组件提前并不知道它们的孩子元素(children)。对Sidebar 或者Dialog 这些通用的”boxes” 的组件来说尤其常见。

我们通常建议这种组件使用children prop 作为孩子元素(children elments)直接作为输出:

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 标签中的任何东西都可以作为FancyBorder 组件的children prop 传入。由于Fancyborder<div> 标签中渲染{props.chidren} ,所以传入的elements 最终被输出显示。

虽然这不是常见的的,但是有时候,你需要多个“占位符”(holes),在一个component 中。在这种情况下,你可以使用自定义的 prop(属性),而不是使用 children ::

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

function App(){
  return (
    <SplitPanel
      left={
        <Contacts />
      }
      right={
        <Chat />
      }/>
  )
}

在CodePen 上尝试

<Contacts /><Chat /> 这种React elements 就是一个object,你可以像其它数据一样将其作为props 传入。

特例

有时我们考虑到组件可以作为其它组件的“特例(special cases)”。例如,我们可以说WelcomeDialogDialog 的一个“特例(special cases)”。

在React 中,这也可以通过组合来实现,通过使用props 来配置实现在一个 “特殊的(special)” 组件中在一个“常用的(generic)”组件中渲染:

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 visting 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 Component {
  constructor(props){
    super(props)
    this.handleChange = this.handleChange.bind(this)
    this.handleSignUp = this.handleSignUp.bind(this)
    this.state = {
      login: ''
    }
  }

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

  handleSignUp(){
    alert(`Welcome aboard, ${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>
    )
  }
}

在CodePen 上尝试

如何看待继承?

在Facebook 中,我们使用成千上万个组件,我们还没有发现任何需要继承来实现的组件。

Props 和组合可以让你灵活的配置组件的样式和行为通过准确和安全的方式。记住组件可以接受任何props,包括原生值(primitive values),React elements 或者是functions。

如果你想在组件之间复用无显示(non-UI)功能,我们建议提取一个独立的JavaScript module。这个组件无需扩展就可以通过import 来使用这个function,object,或者一个class。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值