封装与解耦,组合与继承

封装与解耦,组合与继承

在react的官方文档中,有这么一节Composition vs Inheritance,个人理解就是'组合与继承'.因为在当前的项目中,发现组件之间有多重继承的方式,不知羞耻的说,从事编程以来,还没有写过复杂的继承,顶多就是在prototype上面去扩展一些公共的方法,写的都是一些比较简单的继承.

当前项目的特点:

  1. 组件复杂,封装的很深,组件内部根据传参不同来if..else实现不同功能
  2. 各种函数,方法之间需要多重的参数传递,而且注释不明朗,不知前因后果的话,会非常困惑于代码段中的某一个参数或者方法.

个人理解

  • 这里的组合并不是我们通常说的组件化之间的组合,这里说的组合,是一种***砖块 < 墙 < 毛坯房***的组合,砖块组合成墙,墙搭建成毛坯房,是三个层次之间的组合,不是1000块砖垒成墙,10面墙组成房子的那种同级组合.每个层级都需要其***内部各层级***提供的功能,最外层组件其实是***组合了内部几层***组件的特点,是has-a 和 is-a的区别.
  • 最新的Angular 1.6.5, 和Angular2/4/5版本也是这种组合,具体可以看ngMaterial的示例,里面很好的应用了这种组合特性

react文档加个人理解

react拥有强大的组合模型,react官方强烈建议: 用***组合***而不是***继承***来实现代码复用

在这一节中,我们将会举几个例子,在以往的开发中常常是用***继承***去实现的,这里我们用***组合***的方式去实现这些功能

容器(Containment)

像***侧边栏(Sidebar)***或者***弹窗(Dialog)***之类的组件,在一开始定义的时候,是不知道它的内容具体要展示什么样子的(可能是一行文本,一段html代码,设置是一个react组件)

1.用children这个属性直接传入需要显示的内容

定义组件:

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">
				ContentContent
			</p>
		</FancyBorder>
	)
}

如此一来,WelcomeDialog, 任何在<FancyBorder>标签中的内容都被传递到了FancyBorder,作为它的props.children,最终被渲染到页面中,你可以通过CodePen并打开控制台来看它的具体渲染结果.

然而很多时候,我们在一个组件中需要传入多个"子组件",当这些"子组件"很复杂的时候,很明显不能通过上面的方式囫囵一通的把所有内容都写在一起.这时候我们就需要通过props来实现

2. 通过props实现多个***占位符***

定义组件:

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 />是一个jsx对象,同样你还可以传入其他类型的数据

3. 具象化(Specialization)

有时候我们需要把一个通用的组件(Dialog)更加的具象化(WelcomeDialog),然后去复用这个具象化后的组件(WelcomeDialog),在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!" />
  );
}

注意!!! 这里***WelcomeDialog < Dialog < FancyBorder***,用了***三层组合***来实现一个特殊的欢迎框CodePen

更复杂的例子,以上都是通过function来生成的react组件,通过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}!`);
  }
}

通过CodePen试一试,这里***SignUpDialog < Dialog < FancyBorder***三个组件组合

关于继承

Facebook大致意思是: 我们用react实现了成千上万个组件,但是没有发现任何组件需要使用***继承层次结构***来实现 最后,还是要强调一下,

  1. 这里的组合是***不同层次之间的组合***,不是***同层次之间的组合***
  2. props接收任意数据类型的传参,包括(原生JS数据类型,React元素,或者函数)

转载于:https://my.oschina.net/boogoogle/blog/918891

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值