0%

九、React中的组件、父子组件、React props父组件给子组件传值、子组件给父组件传值、父组件中通过refs获取子组件属性和方法

详情请点阅读全文

一、概述

  • React中的组件: 解决html 标签构建应用的不足。
  • 使用组件的好处:把公共的功能单独抽离成一个文件作为一个组件,哪里里使用哪里引入。
  • 【父子组件】:组件的相互调用中,我们把调用者称为父组件,被调用者称为子组件

二、父子组件传值

父组件给子组件传值方法分为2步:

1、父:在调用子组件的时候定义一个属性:

1
<Header msg='首页'></Header>

2、 子:子组件里面调用:

1
this.props.msg

【说明】父组件还可以把整个父组件传给子组件(此处存疑,新版本可能已失效)
【父】:

1
<Header home={this}></Header>

【子】:

1
2
3
this.props.home; //获取整个父组件
this.props.home.state.msg; //获取父组件其中的state数据
this.props.home.run; //获取父组件中函数

1.父组件向子组件传【值】示例——–:

0.【App.js】根组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
import './App.css';
import Home from './components/Home.js'; //1.引入首页、新闻组件
import News from './components/news.js';

function App() {
return (
<div className="App">
{/* 2.调用首页、新闻、组件*/}
<Home />
<hr/>
<News />
</div>
);
}
export default App;

1.父1【./components/Home.js】首页组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from 'react';
import Header from './Header.js'; //0.引入 公共头组件

class Home extends Component {
constructor(props){
super(props);
this.state={
title:'首页组件' //1.头部名字
}
}

render() {
return (
<div>
<Header title={this.state.title} /> {/*2.用title传此页面的名字到header.js子组件*/}
</div>
);
}
}
export default Home;

3.父2【./components/News.js】新闻组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from 'react';
import Header from './Header.js'; //0.引入 公共头组件

class News extends Component {
constructor(props){
super(props);
this.state={
title:'新闻组件' //1.头部名字
}
}

render() {
return (
<div>
<Header title={this.state.title} /> {/*2.用title传此页面的名字到header.js子组件*/}
</div>
);
}
}
export default News;

3.子【./components/Header.js】公共头组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from 'react';

class Header extends Component {
constructor(props){
super(props);

this.state={
title:'头部组件'
}
}

render() {
return (
<div>
<h1>{this.props.title}</h1> {/*2.接收来自父组件传来的title*/}
</div>
);
}
}
export default Header;

效果:在根组件引入首页、新闻组件效果:

  • 首页组件:引用头部组件,并向其传入title:首页组件
  • 新闻组件:引用头部组件,并向其传入title:新闻组件
  • 达到:用同一个 头部组件,显示自己的头部的目的;
    在这里插入图片描述

    2.父组件向子组件传【方法】示例———-:

    【Home.js】:
    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
    import React, { Component } from 'react';
    import Header from './Header.js';

    class Home extends Component {
    constructor(props){
    super(props);
    this.state={
    title:'首页组件'
    }
    }

    //1.准备向子组件header传的方法
    hello=()=>{
    alert('这是首页组件的hello方法!')
    }

    render() {
    return (
    <div>
    {/*2.把父组件的方法传到子组件前,要先在此处写 hi={this.hello} */}
    <Header title={this.state.title} hi={this.hello} />
    </div>
    );
    }
    }
    export default Home;

【Header.js】:
注意:此传的Home父组件的方法,只能在此Home父组件,内使用;在如新闻组件内,执行此方法则无效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import React, { Component } from 'react';

class Header extends Component {
constructor(props){
super(props);

this.state={
title:'头部组件'
}
}

render() {
return (
<div>
<h1>{this.props.title}</h1>
{/* 1.在子组件内执行父组件传过来的方法;
2.此处的this.props.xxx 取决于父组件的xxx名,xxx={this.ff} */}
<button onClick={this.props.hi}>执行首页组件传过来的hello方法</button>
</div>
);
}
}
export default Header;

效果:
在这里插入图片描述

3.传递整个父组件到子组件【此方法在最新版本无法正确引用可能已取消】

Home.js【方法存疑】

1
2
3
4
5
//1.准备向子组件header传的方法
hello=()=>{
alert('这是首页组件的hello方法!')
}
<Header home={this} />

Header.js【方法存疑】

1
<button onClick={this.props.home.hello}>执行首页组件内的方法hello</button>

报错:

1
2
3
4
5
6
7
8
9
10
11
TypeError: Cannot read property 'hello' of undefined
Header.render
C:/Users/Administrator/Desktop/react/my-app/src/components/Header.js:17
14 | <div>
15 | <h1>{this.props.title}</h1>
16 | {/* 1.在子组件内执行父组件任何部分数据、方法 */}
> 17 | <button onClick={this.props.home.hello}>执行首页组件内的方法hello</button>
| ^ 18 |
19 |
20 | </div>
View compiled

4.子组件(header.js)调用父组件(home.js)的state数据

父【home.js】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import React, { Component } from 'react';
import Header from './Header.js';

class Home extends Component {
constructor(props){
super(props);
this.state={
title:'首页组件',
msg:'首页的消息!'
}
}

render() {
return (
<div>
{/*3.把父组件state.msg数据,传给子组件(header.js) */}
<Header home={this.state.msg} />
<h2>这是首页组件的内容</h2>
</div>
);
}
}
export default Home;

子【header.js】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React, { Component } from 'react';

class Header extends Component {
constructor(props){
super(props);
this.state={
title:'头部组件'
}
}

render() {
return (
<div>
<h1>{this.props.title}</h1>
{/* 1.在子组件内执行父组件的state.msg。(来自home={this.state.msg}) */}
{this.props.home}

</div>
);
}
}
export default Header;

5.子组件调用父组件的函数,且向其传递消息 (此方法已失效)

home.js

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
import React, { Component } from 'react';
import Header from './Header.js';

class Home extends Component {
constructor(props){
super(props);
this.state={
title:'首页组件',
msg:'首页的消息!'
}
}

//1.准备向子组件header传的方法,child_msg为接收来自子组件的消息
hello=(child_msg)=>{
alert('这是首页组件的hello方法!'+child_msg)
}

render() {
return (
<div>
{/*3.把父组件[方法hello]传给子组件 [ he={this.hello} ] */}
<Header title={this.state.title} hello={this.hello} />
<h2>这是首页组件的内容</h2>
</div>
);
}
}
export default Home;

header.js

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
import React, { Component } from 'react';

class Header extends Component {
constructor(props){
super(props);

this.state={
title:'头部组件'
}
}

render() {
return (
<div>
<h1>{this.props.title}</h1>
{/*
功能:子组件调用父组件的hello函数,并向其传自己的消息
1.在子组件内[向]父组件传数据[.bind(this,'消息')];
2.父组件对应的函数要有能接收参数
*/}
<button onClick={this.props.hello.bind(this,'子组件的消息')}></button>

</div>
);
}
}
export default Header;

【父子组件传值的应用场景】

  1. 首先写了一个公共组件:【头部组件】,其它组件都会用到头部这个组件,但会稍有不同;
  2. 在【首页组件】调用 【头部组件】时,想要它显示成【首页头部组件】
  3. 在【新闻组件】调用 【头部组件】时,想要它显示成【新闻头部组件】

此时,就可用父组件向子组件传值来解决这个问题,让【头组件】在对应页面显示【xxx头部组件】…
在这里插入图片描述

三、父组件主动获取子组件的state数据、函数

  1. 调用子组件的时候指定ref的值
    1
    <Header ref='header'></Header>
    1. 通过this.refs.header 获取整个子组件实例
      1
      this.refs.header

      1.实例:从父组件调用子组件的state数据

      Home.js
      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
      import React, { Component } from 'react';
      import Header from './Header.js';
      import Footer from './footer.js'

      class Home extends Component {
      constructor(props){
      super(props);
      this.state={
      title:'首页组件',
      msg:'首页的消息!'
      }
      }

      //2.函数:获取底部组件的state.msg数据
      getfooter=()=>{
      alert(this.refs.foo.state.msg);
      }

      render() {
      return (
      <div>

      <Header title={this.state.title} hello={this.hello} />
      <h2>这是首页组件的内容</h2>

      <hr/>
      {/*1.获取底部子组件的内部函数、state消息需先在底组件上定义 ref='foo' */}
      <Footer ref='foo' />
      {/*3.执行自写函数 调用子组件的state.msg*/}
      <button onClick={this.getfooter}>获取底组件的state.msg</button>
      <br/>

      </div>
      );
      }
      }
      export default Home;

footer.js

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
import React, { Component } from 'react';

class Footer extends Component {
constructor(props){
super(props);

this.state={
title:'底部组件',
msg:'来自底部组件的state.msg消息'
}
}

footer_run=()=>{
alert('底部组件函数消息!')
}

render() {
return (
<div>
<h3>这是一个底部组件</h3>

</div>
);
}
}
export default Footer;

app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React from 'react';
import './App.css';
import Home from './components/Home.js';
import News from './components/news.js';

function App() {
return (
<div className="App">
<Home />
<hr/>

</div>
);
}
export default App;

结果
在这里插入图片描述

2.实例:从父组件调用子组件的方法

【home.js】

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
import React, { Component } from 'react';
import Header from './Header.js';
import Footer from './footer.js'

class Home extends Component {
constructor(props){
super(props);
this.state={
title:'首页组件',
msg:'首页的消息!'
}
}

//2.函数:获取底部组件的state.msg数据
getfooter=()=>{
this.refs.foo.footer_run();
}

render() {
return (
<div>

<Header title={this.state.title} hello={this.hello} />
<h2>这是首页组件的内容</h2>

<hr/>
{/*1.获取底部子组件的内部函数、state消息需先在底组件上定义 ref='foo' */}
<Footer ref='foo' />
{/*3.执行自写函数 调用子组件的footer_run()函数*/}
<button onClick={this.getfooter}>获取底组件的footer_run()函数</button>
<br/>

</div>
);
}
}
export default Home;

【footer.js】

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
import React, { Component } from 'react';

class Footer extends Component {
constructor(props){
super(props);

this.state={
title:'底部组件',
msg:'来自底部组件的state.msg消息'
}
}

footer_run=()=>{
alert('底部组件footer_run函数的消息!')
}

render() {
return (
<div>
<h3>这是一个底部组件</h3>

</div>
);
}
}
export default Footer;

【app.js】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react';
import './App.css';
import Home from './components/Home.js';
import News from './components/news.js';

function App() {
return (
<div className="App">
<Home />
<hr/>
</div>
);
}
export default App;

结果:
在这里插入图片描述