美文网首页
React - 组件复合

React - 组件复合

作者: 闪电西兰花 | 来源:发表于2020-08-14 10:52 被阅读0次
  • 组件复合 - Composition,是另一种区别于高阶组件的一种对扩展组件的方式,可以理解为Vue中的slot
  • 下面我们有一个 Diaolog组件,作为容器,只规定了外层样式,具体的插入的内容由插入的组件决定
// src/components/Composition.js
import React from 'react'

// Dialog作为容器不关心内容和逻辑,只负责提供外层样式
// 插入的内容{props.children}可理解为vue中的slot
function Dialog (props) {
  return (  
    <div style={{ border: "4px solid red"}}>
      {/* children是固定写法 */}
      {props.children}
    </div>
  )
}

// WelcomeDialog组件通过复合提供内容
function WelcomeDialog (props) {
  return (
    <Dialog>
      <h1>welcome</h1>
      <p>感谢使用</p>
    </Dialog>
  )
}

export default function () {
  return (
    <div>
      <WelcomeDialog></WelcomeDialog>
    </div>
  )
}
复合组件WelcomeDialog.jpg
  • Dialog 组件设置的边框颜色可以改成可配置的
// src/components/Composition.js
import React from 'react'

function Dialog (props) {
  return (  
    // 边框默认颜色为red,如果有配置则获取配置颜色
    <div style={{ border: `4px solid ${props.color || 'red'}` }}>
      {/* children是固定写法 */}
      {props.children}
    </div>
  )
}

function WelcomeDialog (props) {
  return (
    <Dialog {...props}>
      <h1>welcome</h1>
      <p>感谢使用</p>
    </Dialog>
  )
}

export default function () {
  return (
    <div>
      <WelcomeDialog color={'blue'}></WelcomeDialog>
    </div>
  )
}
  • 复合组件也可以像Vue中一样使用具名插槽,在组件中插入的这部分内容对应显示在容器组件同名的位置
// src/components/Composition.js
import React from 'react'

// 这里可以看出props.children、props.footer都可以是JSX
// props.children可以写成任意的Js表达式
function Dialog (props) {
  return (  
    // 边框默认颜色为red,如果有配置则获取配置颜色
    <div style={{ border: `4px solid ${props.color || 'red'}` }}>
      {/* children是固定写法 */}
      {props.children}
      {/* 具名插槽 footer */}
      <div className="footer">
        {props.footer}
      </div>
    </div>
  )
}

export default function () {
  let footer = <button onClick={() => {alert('confirm')}}>this is footer</button>
  return (
    <div>
      <WelcomeDialog color={'blue'} footer={footer}></WelcomeDialog>
    </div>
  )
}
  • 前面说了 props.chilrdren 可以是任意Js表达式,所以 props.chilrdren 肯定可以是一个函数,然后我们用函数的形式模拟Vue中的作用域插槽
// src/components/Composition.js
import React from 'react'

// 模拟这里是异步调用
const Api = {
  getUser() {
    return {name: 'asher', age: 3}
  }
}

function Fetcher (props) {
  // 通过组件传进来的属性调用api获取数据
  let user = Api[props.name]();
  // 这里的props.children是个函数
  return props.children(user)
}

export default function () {
  return (
    <div>
      <Fetcher name="getUser"> 
        // 因为props.children是个函数,所以在这里直接调用
        {({name, age}) => (
          <p>{name} - {age}</p>
        )}
      </Fetcher>
    </div>
  )
}
  • 再试一试 props.children 是一个数组的时候,做一个简单的过滤器
// src/components/Composition.js
import React from 'react'

function Filter (props) {
  return (
    <div>
      {React.Children.map(props.children, child => {
        if(child.type !== props.type) {
          return;
        }
        // return过滤之后的数组
        return child;
      })}
    </div>
  )
}

export default function () {
  return (
    <div>
      {/* 过滤器 过滤出指定标签*/}
      <Filter type="h5">
        <h5>re</h5>
        <h5>eae</h5>
        <p>this is p</p>
      </Filter>
    </div>
  )
}
  • 复合组件中还可以修改 children,这里我们做一个单选按钮组件,我们都知道同组单选按钮要想实现单选必须拥有相同的 name 属性,这里我们需要实现这个 name属性由父组件 RadioGroup 决定并传递给每一个子组件 Radio
// src/components/Composition.js
import React from 'react'

// 修改children
function RadioGroup (props) {
  return (
    <div>
      {/* RadioGroup遍历自己的children,并分别给他们加上相同的name属性 */}
      {React.Children.map(props.children, child => {
        // vdom不可更改,必须先clone一个再做更改
        // 不可以写成 child.props.name = props.name
        return React.cloneElement(child, {name:props.name})
      })}
    </div>
  )
}

function Radio ({children, ...rest}) {
  // 因为Radio组件中还有内容,所以要特别处理children
  // 将传进来的props分成2部分,分别是children和其他属性
  return (
    <label>
      <input type="radio" {...rest}></input>
      {children}
    </label>
  )
}

export default function () {
  return (
    <div>
      <RadioGroup name="mvvm">
        <Radio value="vue">vue</Radio>
        <Radio value="react">react</Radio>
        <Radio value="angular">angular</Radio>
      </RadioGroup>
    </div>
  )
}

相关文章

  • React - 组件复合

    组件复合 - Composition,是另一种区别于高阶组件的一种对扩展组件的方式,可以理解为Vue中的slot ...

  • react-router路由守卫

    安装redux和react redux index.js 用react-redux的Provider复合组件实现逐...

  • react复合组件封装思想(props截取)

    封装react组件经常会封装一些复合组件,比如手风琴,轮播图,等等……与常规组件不一样,复合组件经常会遇到一个问题...

  • Typescript写复合组件

    前言 环境React,Typescript。 某些场景下复合组件比多个组件更方便。比如antd的Menu、Menu...

  • react中的组件复合,用于抽离js

    react中的组件复合类似于vue的插槽 react推荐我们当组件间有共同的js逻辑时候,可以进行抽离而不是继承。...

  • React复合组件

    http://reactjs.cn/react/docs/multiple-components.html

  • shadow dom是什么

    Shadow DOM:我们知道Vue和react有组件概念,可以通过普通标签封装复合需求的组件,shadow do...

  • React基础知识点总结

    本文目录: 1.React⼊⻔ 2.JSX语法 3.组件 4.正确使用setState 5.⽣命周期 6.组件复合...

  • <六>React复合组件

    概念理解 复合组件其实就是组件内部嵌套组件 代码实现

  • React入门 (4)-组件复合

    组件复合 - Composition 简单来说将公用的组件抽离,类似与Vue里面的插槽 不具名 1.src\Lay...

网友评论

      本文标题:React - 组件复合

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