react - 定义组件 - Props

时间:2024-10-07 15:17:12

五、Props

5.1 Props详解

props是正常是外部传入的,组件内部也可以通过一些方式来初始化的设置,属性不能被组件自己更改,但是你可以通过父组件主动重新渲染的方式来传入新的 props

React 非常灵活,但它也有一个严格的规则:

所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。

纯函数:输入一定,输出一定确定

总的来说,在使用一个组件的时候,可以把参数放在标签的属性当中,所有的属性都会作为组件 props 对象的键值。

通过箭头函数创建的组件,需要通过函数的参数来接收props

通过类创建的组件,需要通过 来接收

组件可以在其输出中引用其他组件。

这就可以让我们用同一组件来抽象出任意层次的细节。

按钮,表单,对话框,甚至整个屏幕的内容:在 React 应用程序中,这些通常都会以组件的形式表示。

5.2 父子组件通信

5.2.1 构建一个父子组件

src/

// src/
import React from 'react'
import ReactDOM from 'react-dom/client'

// 引入react组件时,后缀名可以不写
import App from './01_props/01_Parent_Child'

const root = (('#root'))

(<App />)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

src/01_props/01_Parent_Child.jsx

// src/01_props/01_Parent_Child.jsx
// React组件的后缀名 既可以是js  也可以jsx
import React from 'react'

class Child extends  {
  render () {
    return (
      <div>子组件</div>
    )
  }
}

class Parent extends  {
  render () {
    return (
      <div>
        父组件
        <hr />
        <Child />
      </div>
    )
  }
}

class App extends  {
  render () {
    return (
      <div>
        <h1>父子组件</h1>
        <Parent />
      </div>
    )
  }
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

5.2.2 父组件给子组件传值

src/

// src/
import React from 'react'
import ReactDOM from 'react-dom/client'

// import App from './01_props/01_Parent_Child' // 父子组件省略.jsx
import App from './01_props/02_Parent_Child_value' // 父组件给子组件传值

const root = (('root'))

// 标签形式调用
(<App />)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

src/01_props/02_Parent_Chil_value.jsx

// src/01_props/02_Parent_Child_value.jsx
import React from 'react'
/**
 * 1.父组件在调用子组件的地方,添加自定义的属性,
 *   如果属性的值是变量、boolean类型、number类型、对象、数组、null、undefined,
 *   使用 {} 包裹
 * 2.子组件通过props属性接收父组件传递的值
 *   2.1 如果子组件是类组件,将在jsx代码中可通过  获取父组件的值
 *   2.2 如果子组件是函数式组件, 默认参数为props,即可获得父组件的值
 */

const Child2 = (props) => {
  return (
    <div>
      子组件2
      <div>str: {  }</div>
      <div>flag: {  + '' }</div>
      <div>num: {  }</div>
      <div>: {  }</div>
      <div>arr: {  }</div>
    </div>
  )
}

class Child1 extends  {
  render () {
    return (
      <div>
        子组件1
        <div>str: {  }</div>
        <div>flag: {  + '' }</div>
        <div>num: {  }</div>
        <div>: {  }</div>
        <div>arr: {  }</div>
      </div>
    )
  }
}

class Parent extends  {

  render () {
    const str1 = 'str1'
    const str2 = 'str2'

    return (
      <div>
        父组件
        <hr />
        <Child1 
          str = { str1 }
          flag = { true }
          num = { 1 }
          obj = { { a: 1 } }
          arr = { [1, 2, 3] }
        />
        <hr />
        <Child2 
          str = { str2 }
          flag = { false }
          num = { 2 }
          obj = { { a: 2 } }
          arr = { [4, 5, 6] }
        />
      </div>
    )
  }
}

class App extends  {
  render () {
    return (
      <div>
        <h1>父子组件</h1>
        <Parent />
      </div>
    )
  }
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

5.2.3 父组件给子组件传值设置默认值

src/

// src/
import React from 'react'
import ReactDOM from 'react-dom/client'

// 引入react组件时,后缀名可以不写
// import App from './01_props/01_Parent_Child' // 父子组件
// import App from './01_props/02_Parent_Child_value' // 父组件给子组件传值
import App from './01_props/03_Parent_Child_default' // 父组件给子组件传值,子组件设置默认值

const root = (('#root'))

(<App />)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

src/01_props/03_Parent_Chil_default.jsx

// src/01_props/03_Parent_Child_default.jsx
import React from 'react'
/**
 * 1.父组件在调用子组件的地方,添加自定义的属性,
 *   如果属性的值是变量、boolean类型、number类型、对象、数组、null、undefined,
 *   使用 {} 包裹
 * 2.子组件通过props属性接收父组件传递的值
 *   2.1 如果子组件是类组件,将在jsx代码中可通过  获取父组件的值
 *   2.2 如果子组件是函数式组件, 默认参数为props,即可获得父组件的值
 * 3.父给子传值是,如果需要设定 默认值,通用(类组件以及函数式组件)的写法
 *    在定义组件之后,通过 组件.defaultProps 设置默认值
 *    如果子组件是类组件,还可以通过 类的静态属性 设置默认值
 */

const Child2 = (props) => {
  return (
    <div>
      子组件2
      <div>str: {  }</div>
      <div>flag: {  + '' }</div>
      <div>num: {  }</div>
      <div>: {  }</div>
      <div>arr: {  }</div>
      <div>test: {  }</div>
    </div>
  )
}
 = {
  test: 'test2'
}

class Child1 extends  {
  // 类的静态属性
  static defaultProps = {
    test: 'test1111'
  }
  render () {
    return (
      <div>
        子组件1
        <div>str: {  }</div>
        <div>flag: {  + '' }</div>
        <div>num: {  }</div>
        <div>: {  }</div>
        <div>arr: {  }</div>
        <div>test: {  }</div>
      </div>
    )
  }
}
//  = {
//   test: 'test1'
// }

class Parent extends  {

  render () {
    const str1 = 'str1'
    const str2 = 'str2'

    return (
      <div>
        父组件
        <hr />
        <Child1 
          str = { str1 }
          flag = { true }
          num = { 1 }
          obj = { { a: 1 } }
          arr = { [1, 2, 3] }
        />
        <hr />
        <Child2 
          str = { str2 }
          flag = { false }
          num = { 2 }
          obj = { { a: 2 } }
          arr = { [4, 5, 6] }
        />
      </div>
    )
  }
}

class App extends  {
  render () {
    return (
      <div>
        <h1>父子组件</h1>
        <Parent />
      </div>
    )
  }
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

5.2.4 使用prop-types属性验证

自 React v15.5 起, 已移入另一个包中。请使用 prop-types 库 代替。

$ cnpm i prop-types -D

import PropTypes from 'prop-types';

 = {
// 你可以将属性声明为 JS 原生类型,默认情况下
// 这些属性都是可选的。
optionalArray: ,
optionalBool: ,
optionalFunc: ,
optionalNumber: ,
optionalObject: ,
optionalString: ,
optionalSymbol: ,

// 任何可被渲染的元素(包括数字、字符串、元素或数组)
// (或 Fragment) 也包含这些类型。
optionalNode: ,

// 一个 React 元素。
optionalElement: ,

// 一个 React 元素类型(即,MyComponent)。
optionalElementType: ,

// 你也可以声明 prop 为类的实例,这里使用
// JS 的 instanceof 操作符。
optionalMessage: (Message),

// 你可以让你的 prop 只能是特定的值,指定它为
// 枚举类型。
optionalEnum: (['News', 'Photos']),

// 一个对象可以是几种类型中的任意一个类型
optionalUnion: ([
 ,
 ,
 (Message)
]),

// 可以指定一个数组由某一类型的元素组成
optionalArrayOf: (),

// 可以指定一个对象由某一类型的值组成
optionalObjectOf: (),

// 可以指定一个对象由特定的类型值组成
optionalObjectWithShape: ({
 color: ,
 fontSize: 
}),

// An object with warnings on extra properties
optionalObjectWithStrictShape: ({
 name: ,
 quantity: 
}),

// 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
// 这个 prop 没有被提供时,会打印警告信息。
requiredFunc: ,

// 任意类型的必需数据
requiredAny: ,

// 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
// 请不要使用 `` 或抛出异常,因为这在 `oneOfType` 中不会起作用。
customProp: function(props, propName, componentName) {
 if (!/matchme/.test(props[propName])) {
   return new Error(
     'Invalid prop `' + propName + '` supplied to' +
     ' `' + componentName + '`. Validation failed.'
   );
 }
},

// 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
// 它应该在验证失败时返回一个 Error 对象。
// 验证器将验证数组或对象中的每个值。验证器的前两个参数
// 第一个是数组或对象本身
// 第二个是他们当前的键。
customArrayProp: (function(propValue, key, componentName, location, propFullName) {
 if (!/matchme/.test(propValue[key])) {
   return new Error(
     'Invalid prop `' + propFullName + '` supplied to' +
     ' `' + componentName + '`. Validation failed.'
   );
 }
})
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

src/

// src/
import React from 'react'
import ReactDOM from 'react-dom/client'

// 引入react组件时,后缀名可以不写
// import App from './01_props/01_Parent_Child' // 父子组件
// import App from './01_props/02_Parent_Child_value' // 父组件给子组件传值
// import App from './01_props/03_Parent_Child_default' // 父组件给子组件传值,子组件设置默认值
import App from './01_props/04_Parent-Child_type' // 父组件给子组件传值,子组件设置默认值,验证数据类型

const root = (('#root'))

(<App />)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

src/01_props/04_Parent_Chil_type.jsx

// src/01_props/04_Parent_Child_type.jsx
import React from 'react'
import PropTypes from 'prop-types'
/**
 * 1.父组件在调用子组件的地方,添加自定义的属性,
 *   如果属性的值是变量、boolean类型、number类型、对象、数组、null、undefined,
 *   使用 {} 包裹
 * 2.子组件通过props属性接收父组件传递的值
 *   2.1 如果子组件是类组件,将在jsx代码中可通过  获取父组件的值
 *   2.2 如果子组件是函数式组件, 默认参数为props,即可获得父组件的值
 * 3.父给子传值是,如果需要设定 默认值,通用(类组件以及函数式组件)的写法
 *    在定义组件之后,通过 组件.defaultProps 设置默认值
 *    如果子组件是类组件,还可以通过 类的静态属性 设置默认值
 * 
 * 4.如果需要给子组件的值设置数据类型的校验,通过第三方的 prop-types 来完成
 *   定义好组件之后, 通过 组件.propTypes 设置
 */

const Child2 = (props) => {
  return (
    <div>
      子组件2
      <div>str: {  }</div>
      <div>flag: {  + '' }</div>
      <div>num: {  }</div>
      <div>: {  }</div>
      <div>arr: {  }</div>
      <div>test: {  }</div>
    </div>
  )
}
 = {
  test: 'test2'
}
 = {
  str: ,
  flag: ,
  num: ([ ,  ]).isRequired,
  obj: ,
  arr: ,
  // test: 
  test (props, propName, componentName) {
    (props)
    (propName)
    (componentName)
    if (props[propName].length < 6) { // 验证规则可自定义
      return new Error('出错了')
    }
  }
}

class Child1 extends  {
  // 类的静态属性
  static defaultProps = {
    test: 'test1111'
  }
  render () {
    return (
      <div>
        子组件1
        <div>str: {  }</div>
        <div>flag: {  + '' }</div>
        <div>num: {  }</div>
        <div>: {  }</div>
        <div>arr: {  }</div>
        <div>test: {  }</div>
      </div>
    )
  }
}
//  = {
//   test: 'test1'
// }

 = {
  str: ,
  flag: ,
  num: ([ ,  ]).isRequired,
  obj: ,
  arr: ,
  test: 

}

class Parent extends  {

  render () {
    const str1 = 'str1'
    const str2 = 'str2'

    return (
      <div>
        父组件
        <hr />
        <Child1 
          str = { str1 }
          flag = { true }
          num = { 1 }
          obj = { { a: 1 } }
          arr = { [1, 2, 3] }
        />
        <hr />
        <Child2 
          str = { str2 }
          flag = { false }
          num = { 2 }
          obj = { { a: 2 } }
          arr = { [4, 5, 6] }
        />
      </div>
    )
  }
}

class App extends  {
  render () {
    return (
      <div>
        <h1>父子组件</h1>
        <Parent />
      </div>
    )
  }
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126

5.3

我们知道使用组件的时候,可以嵌套。要在自定义组件中使用嵌套结构,就需要使用

等同于 vue中的 slot 插槽

src/

// src/
import React from 'react'
import ReactDOM from 'react-dom/client'

// 引入react组件时,后缀名可以不写
// import App from './01_props/01_Parent_Child' // 父子组件
// import App from './01_props/02_Parent_Child_value' // 父组件给子组件传值
// import App from './01_props/03_Parent_Child_default' // 父组件给子组件传值,子组件设置默认值
// import App from './01_props/04_Parent-Child_type' // 父组件给子组件传值,子组件设置默认值,验证数据类型
import App from './01_props/05_App_props_children' // 类插槽

const root = (('#root'))

(<App />)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

src/01_props/05_App_props_children.jsx

// src/01_props/05_App_props_children.jsx

import { Component } from "react";
const Content = (props) => {
  return (
    // <div>这里是内容</div>
    <div>这里是{  }内容</div>
  )
}

class Header extends Component {
  render () {
    return (
      // <h1>这里是头部</h1>
      <h1>这里是{  }头部</h1>
    )
  }
}

class App extends Component {
  render () {
    return (
      <div>
        <Header>首页</Header>
        <Content>首页 </Content>
        <hr />
        <Header>分类</Header>
        <Content>分类 </Content>
      </div>
    )
  }
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

如果需要给组件添加多个元素,并且显示在多个位置,可以如下设置:

src/

// src/
import React from 'react'
import ReactDOM from 'react-dom/client'

// 引入react组件时,后缀名可以不写
// import App from './01_props/01_Parent_Child' // 父子组件
// import App from './01_props/02_Parent_Child_value' // 父组件给子组件传值
// import App from './01_props/03_Parent_Child_default' // 父组件给子组件传值,子组件设置默认值
// import App from './01_props/04_Parent-Child_type' // 父组件给子组件传值,子组件设置默认值,验证数据类型
// import App from './01_props/05_App_props_children' // 类插槽
import App from './01_props/06_App_mutiple_props_children' // 类具名插槽 多个插槽 

const root = (('#root'))

(<App />)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

src/01_props/06_App_mutiple_props_children.jsx

// src/01_props/06_App_mutiple_props_children.jsx

import { Component } from "react";


class Header extends Component {
  render () {
    ()
    return (
      <ul>
        <li>左侧: { [0] }</li>
        <li>中间: { [1] }</li>
        <li>右侧: { [2] }</li>
      </ul>
    )
  }
}

class App extends Component {
  render () {
    return (
      <div>
        <Header>
          <div>城市</div>
          <div>搜索</div>
          <div>登录</div>
        </Header>
        <hr />
        <Header>
          <div>返回</div>
          <div>标题</div>
          <div>更多</div>
        </Header>
      </div>
    )
  }
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

实现类似vue的具名插槽,需要通过 的下标去访问

5.4 render props特性

使用 Render Props 来解决横切关注点(Cross-Cutting Concerns)

组件是 React 代码复用的主要单元,但如何将一个组件封装的状态或行为共享给其他需要相同状态的组件并不总是显而易见。

以下组件跟踪 Web 应用程序中的鼠标位置:

src/

// src/
import React from 'react'
import ReactDOM from 'react-dom/client'

// import App from './01_props/01_Parent_Child' // 父子组件省略.jsx
// import App from './01_props/02_Parent_Child_value' // 父组件给子组件传值
// import App from './01_props/03_Parent_Child_default' // 父组件给子组件传值,子组件设置默认值
// import App from './01_props/04_Parent-Child_type' // 父组件给子组件传值,子组件设置默认值,并且验证数据类型
// import App from './01_props/05_App_props_children' // 类插槽
// import App from './01_props/06_App_mutiple_props_children' // 类具名插槽(多个插槽)
import App from './01_props/07_App_mouse_tracker' // 鼠标跟随

const root = (('root'))

// 标签形式调用
(<App />)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

src/01_props/07_App_mouse_tracker.jsx

还没有学习状态state以及事件处理,这里先用

// src/01_props/07_App_mouse_tracker.jsx
// 先行使用 状态  事件
import React from 'react'

class App extends  {
  constructor (props) {
    super(props)
     = {
      x: 0, y: 0
    }
  }

  render () {
    return (
      <div style = { { 
        width: '100vw', 
        height: '100vh', 
        backgroundColor: '#efefef'
      } }
        onMouseMove = { (event) => { // event的值是默认的参数的zhi
          ({ // 即为修改状态的方式
            x: ,
            y: 
          })
        } }
      >
        <div>x: {  },y: {  }</div>
      </div>
    )
  }
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

当光标在屏幕上移动时,组件在 <div> 中显示其坐标。

现在的问题是:我们如何在另一个组件中复用这个行为?换个说法,若另一个组件需要知道鼠标位置,我们能否封装这一行为,以便轻松地与其他组件共享它?

render prop 是一个用于告知组件需要渲染什么内容的函数 prop。

src/

// src/
import React from 'react'
import ReactDOM from 'react-dom/client'

// 引入react组件时,后缀名可以不写
// import App from './01_props/01_Parent_Child' // 父子组件
// import App from './01_props/02_Parent_Child_value' // 父组件给子组件传值
// import App from './01_props/03_Parent_Child_default' // 父组件给子组件传值,子组件设置默认值
// import App from './01_props/04_Parent-Child_type' // 父组件给子组件传值,子组件设置默认值,验证数据类型
// import App from './01_props/05_App_props_children' // 类插槽
// import App from './01_props/06_App_mutiple_props_children' // 类具名插槽 多个插槽 
// import App from './01_props/07_App_mouse_tracker' // 鼠标跟随 
import App from './01_props/08_App_render_props' // 渲染属性 - 其他组件共享状态

const root = (('#root'))

(<App />)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

src/01_props/08_App_render_props.jsx

// src/01_props/08_App_render_props.jsx
import React, { Component } from 'react'
// 渲染属性共享组件的状态
// 在调用需要共享的组件(Mouse)上,添加一个render的自定义属性,该属性是一个自定义函数
// 在自定义函数的内部返回需要共享给的那个组件(Cat)
// 在需要共享的组件(Mouse)内部,通过 () 或者 () 即可调用,参数即为需要共享的状态
// 那么在定义自定义render属性的函数内部,就会接收到 参数,通过返回的组件(Cat)传递该参数即可

const Cat = (props) => {
  return (
    <div>Cat鼠标位置:({  }, {  })</div>
  )
}
const Dog = (props) => {
  return (
    <div>Dog鼠标位置:({  }, {  })</div>
  )
}

class Mouse extends Component {
  constructor (props) {
    super(props)
     = {
      x: 0, y: 0
    }
  }
  render () {
    return (
      <div style = { { 
        width: '100vw', 
        height: '50vh', 
        backgroundColor: '#efefef'
      } }
        onMouseMove = { (event) => { // event的值是默认的参数的zhi
          ({ // 即为修改状态的方式
            x: ,
            y: 
          })
        } }
      >
        { ({ x: , y:  }) }
      </div>
    )
  }
}

export default class App extends Component {
  render() {
    return (
      <div>
        <Mouse render={ (point) => {
          return <Dog point = { point }/>
        } }>
        </Mouse>
        <hr />
        <Mouse render={ (point) => {
          return <Cat point = { point }/>
        } }>
        </Mouse>
      </div>
    )
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

此案例实际上完成了react中子组件给父组件传值