< 关於 React: 开始打地基| 父组件、子组件、兄弟姐妹组件的关系 >

09-14-2021

本章内容
  • 子组件更新父组件的状态
    • 设定组建间的状态
    • 设定组建间事件处理的程序
  • 子组件更新其他兄弟姐妹的传递方式
    • 确认子组件们之间的引用
    • 组件分工的方式
    • 将显示传递给兄弟姐妹组件
  • 结论
    • 无状态component继承有状态component回顾

子组件更新父组件的状态

设定组建间的状态

首先我们要先知道我们需要在子组件更改的位置并且定义。
是在line10``<h1> Hey my name is {this.props.name}! </h1>
下拉选单选择了显示的项目value会返回给name显示

// Child.js
import React from 'react';

export class Child extends React.Component {
  render() {
    return (
      <div>
        <h1>
          Hey there, I'am {this.props.name}!
        </h1>
        <select id="great-names">
          <option value="Frarthur">
            Frarthur
          </option>

          <option value="Gromulus">
            Gromulus
          </option>

          <option value="Thinkpiece">
            Thinkpiece
          </option>
        </select>
      </div>
    );
  }
}

在父组件中,我们需要先import<Child/>component到页面中。
并且使用setState()定义一个状态的事件。

// Parent.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Child } from './Child';

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name:'Frarthur'};
  }

  changeName(newName){
    this.setState({
      name:newName
    });
  }

  render() {
    return <Child name={this.state.name} />
  }
}

ReactDOM.render(
	<Parent />,
	document.getElementById('app')
);

设定组件间事件处理的程序

以上是状态的设置可以将监听事件传递下去了,接着是要传递事件处理的方式。
bind this changeName()在constructor里面,把函式传递下去给子组件,而要在传递的component上使用onChange把要传递的方法写上去

// Parent.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Child } from './Child';

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name:'Frarthur'};
    this.changeName = this.changeName.bind(this);
  }

  changeName(newName){
    this.setState({
      name:newName
    });
  }

  render() {
    return <Child name={this.state.name} onChange={ this.changeName } />
  }
}

ReactDOM.render(
	<Parent />,
	document.getElementById('app')
);

我们使用props传递方法下来子层,理当会先在需要改变的<select>上放上接props的方式onChange(this.props.onChange)

但我们少了传递props的桥梁,以及需要传递的参数,因为这不会传递一个名称,而是会传递一个事件的物件,所以这个函数应该要接收一个event object作为参数,才可以调用这个函式。

handleChange(e) {
  const name = e.target.value;
  this.props.onChange(name);
}

stateless component 绑定方式

// Child.js

export class Child extends React.Component {
 constructor(props) {
  super(props);
  this.handleChange = this.handleChange.bind(this);
}
  handleChange(e) {
  const name = e.target.value;
  this.props.onChange(name);
}
 
  render() {
    return (
      <div>
        <h1 >
          Hey my name is {this.props.name}!
        </h1>
        <select id="great-names" onChange={this.handleChange}>
          <option value="Frarthur">
            Frarthur
          </option>

子组件更新其他兄弟姐妹的传递方式

  • <Child / ><sibling /> 两个compoents

确认子组件们之间的引用

首先,确认import了<sibling />这个component在页面上,以及在return时有把<sibling / >放进来,最後确认与<Child />,使用同一个外层包装起来的<div></div>

组件分工的方式

<sibling/ > 的主要工作是显示选择的名称,name={this.state.name}要显示的name是存在Parents中的state,所以可以透过名称传递给sibling并且显示。
同时<Child/>的工作是提供更改所选名称的方法,而不是==显示==,所以我们把原本的onChange()与显示的name都从Parents移除

将显示传递给兄弟姐妹组件

我们现在已经将<sibling/>作为prop传递了。
所以我们要在prop显示要传递的name
<sibling/> 中,宣告一个新的变数name,让变数等於prop传递的name,将文句中要替换的名称改为变数,name

// parent.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Child } from './Child';
import { Sibling } from './Sibling';
// 引入子组件

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = { name: 'Frarthur' };
    // 预设要显示的名称
    this.changeName = this.changeName.bind(this);
    // 绑定要更改的方法
  }

// 更改的方法
  changeName(newName) {
    this.setState({
      name: newName
    });
  }

  render() {
    return (
      <div>
        // <Child 
        //   name={this.state.name} 
        //   onChange={this.changeName} />
        // 将原本在一个component中要做的事情分给兄弟姐妹执行
        <Child onChange={this.changeName} />
        // 负责更改名称的方式
        <Sibling name={this.state.name} />
        // 负责更改状态要显示的名字
      </div>
    );
  }
}

ReactDOM.render(
  <Parent />,
  document.getElementById('app')
);

// Child.js
import React from 'react';

export class Child extends React.Component {
  constructor(props) {
    super(props);

    this.handleChange = this.handleChange.bind(this);
    // 绑定更改的方法
  }

// 选择到的value传到方法中
  handleChange(e) {
    const name = e.target.value;
    this.props.onChange(name);
  }

  render() {
    return (
      <div>
        <select
          id="great-names"
          onChange={this.handleChange}>

          <option value="Frarthur">Frarthur</option>
          <option value="Gromulus">Gromulus</option>
          <option value="Thinkpiece">Thinkpiece</option>
        </select>
      </div>
    );
  }
}
// sibling.js
import React from 'react';

export class Sibling extends React.Component {
  render() {
  const name =  this.props.name
// 设定变数接传递的过来的`name`
    return (
      // <div>
      //   <h1>Hey, my name is Frarthur!</h1>
      //   <h2>Don't you think Frarthur is the prettiest name ever?</h2>
      //   <h2>Sure am glad that my parents picked Frarthur!</h2>
      // </div>
    // 原本的标题内容都只能出现一个名称,用变数{name}呈现就会改变名字了!
      <div>
        <h1>Hey, my name is {name}!</h1>
        <h2>Don't you think {name} is the prettiest name ever?</h2>
        <h2>Sure am glad that my parents picked {name}!</h2>
      </div>
    );
  }
}

结论:

无状态component继承有状态component回顾:

  1. 在parent中定义了一个状态的function:this.state
    changeName(newName) { this.setState({ name: newName }); }

  2. 有状态的component将function往下传递给无状态的component
    <Child onChange={this.changeName} />

  3. 这个无状态的class function定义了传递函数,这个传递函数可以做为参数使用
    <Child /> handleChange(e) { const name = e.target.value; this.props.onChange(name); }

  4. 这个无状态组件的componet使用了一个新的方程序当作事件程序
    <Child /> onChange={this.handleChange}>

  5. 当事件发生了改变,parent 的 state状态更新时(选择了下拉选单)

  6. 这个有状态的component就会把状态往下传递给无状态component,这与改变state的方式不同
    <Sibling name={this.state.name} />

  7. 无状态componet class(sibling) 接收到了state 於是就显示它
    <sibling/> const name = this.props.name;

  8. 总的来说,有状态的component只负责render,<Child/ >负责state,负责显示切换的state


<<:  Day14-This

>>:  github

DAY15 注册按钮功能实现

if isinstance(event, PostbackEvent): # 如果有normal讯息...

27 - EditorConfig + Prettier + ESLint + Stylelint + Markdownlint - All you can lint

将各式 linter 与 formatter 工具整合於同个专案中,让开发者可以: 使用 Edito...

【领域展开 28 式】 auther box 文末笔者签名档设定与 Gravatar 认识

下个阶段要来尝试发送第一篇 post,在练习发第一篇文章之前,是有先查阅如何将 medium 的文章...

Day 06 : 什麽是 MLOps

各种商务情境都在思考如何融入 AI 提供更适切的智慧化服务,在Day 04 : 以资料为中心的人工智...

Day18 Lab 2 - Object storage metadata

Object的metadata让我们能快速定位Object在什麽地方、属性等等,可以理解为类似资料库...