web前端高级React - React从入门到进阶之组件的组合使用

系列文章目录

第一章:React从入门到进阶之初识React
第一章:React从入门到进阶之JSX简介
第三章:React从入门到进阶之元素渲染
第四章:React从入门到进阶之JSX虚拟DOM渲染为真实DOM的原理和步骤
第五章:React从入门到进阶之组件化开发及Props属性传值
第六章:React从入门到进阶之state及组件的生命周期
第七章:React从入门到进阶之React事件处理
第八章:React从入门到进阶之React条件渲染
第九章:React从入门到进阶之React中的列表与key
第十章:React从入门到进阶之表单及受控组件和非受控组件
第十一章:React从入门到进阶之组件的状态提升
第十二章:React从入门到进阶之组件的组合使用

包含关系组合

有些时候我们在开发一些通用组件的时候,我们并不能提前知晓它们的子组件的具体内容。比如我们要做一个上下左右布局的页面(即:头部header,左边siderBar,右边Container),这个时候要求右侧的container是要动态显示内容的。这个时候我们就需要使用一个特殊的 children prop 来将他们的子组件传递到渲染结果中:

function Container(props){
    
    
	return <div className="container">
		{
    
    props.children}
	</div>
}

function HomePage(props){
    
    
	return <>
		<Container>
			 <h1 className="title">
        		Hello world
      		</h1>
      		<p className="content">
        		我要显示在container里面!
      		</p>
		</Container>
	</>
}
  • 上面代码中我们Container容器组件,这个组件只是返回一个div然后把props的children属性整体作为div标签的内容
  • 然后我们在HomePage组件中使用Container组件,Container标签中的所有内容都会作为一个 children prop 传递给 Container组件。因为 我们在Container中将 {props.children} 渲染在一个 < div> 中,被传递的这些子组件最终都会出现在输出结果中。

另外还有一些情况,我们可能不像container那样把所有的子组件都包含进来,而是大部分内容是固定的,只有一小部分值动态变化的。这个时候我们就需要在一个组件中预留出几个“洞”。这种情况下,我们可以不使用 children,而是自行约定:将所需内容传给 props,并使用相应的 prop。比如一个聊天内容窗格中,左侧显示联系人,右侧显示聊天内容,其中联系人和聊天内容都是单独的组件,需要主窗格预留出两块空间来显示其它两个组件:

function ChatRoom(props) {
    
    
  return (
    <div>
      <div className="left">
        {
    
    props.concat}
      </div>
      <div className="right">
        {
    
    props.message}
      </div>
    </div>
  );
}

function App() {
    
    
  return (
    <ChatRoom
      concat={
    
    
        <Contacts />
      }
      message={
    
    
        <Chat />
      } />
  );
}

上面的代码中 < Contacts /> 和 < Chat /> 之类的 React 元素本质就是对象(object),所以我们可以把它们当作 props,像其他数据一样传递。这种方法就类似于Vue中“插槽”(slot)的概念,但在 React 中没有“插槽”这一概念的限制,我们可以将任何东西作为 props 进行传递。

特例关系

有些时候,我们会把一些组件看作是其他组件的特殊实例,比如 WelcomeDialog 可以说是 Dialog 的特殊实例。
在 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!" />
  );
}

上面都是以函数组件作为示例来讲解的,那么组合同样也适合在类组件中使用:

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

好了本章内容就介绍到这里,这节的内容比较简单,同时这也是本系列文章中入门级的最后一篇文章。
下一章节开始我们将学习一些React进阶方面的知识,敬请期待。

猜你喜欢

转载自blog.csdn.net/lixiaosenlin/article/details/112796433