React学习笔记(三)——React 组件通讯

1. 组件通讯-概念

了解组件通讯的意义

大致步骤:

  • 知道组件的特点
  • 知道组件通讯意义

具体内容:

  1. 组件的特点
    • 组件是**独立且封闭**的单元,默认情况下,只能使用组件自己的数据
    • 在组件化过程中,通常会将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能
  2. 知道组件通讯意义
    • 而在这个过程中,多个组件之间不可避免的要**共享**某些数据
    • 为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通
    • 这个过程就是组件通讯

总结:

  • 组件状态是独立的,组件化之后涉及状态同步,需要进行组件通讯

2. 组件通讯-props 基本使用

能够通过 props 传递数据和接收数据

大致步骤:

  • 传递数据和接收数据的过程
  • 函数组件使用 props
  • 类组件使用 props

具体内容:

① 传递数据和接收数据的过程

  • 使用组件的时候通过属性绑定数据,在组件内部通过 props 获取即可。

② 函数组件使用 props

javascript 复制代码
// 使用组件
<Hello name="jack" age="20" />
javascript 复制代码
// 定义组件 props包含{name:'jack',age:'20'}
function Hello(props) {
  return <div>接收到数据:{props.name}</div>;
}

③ 类组件使用 props

javascript 复制代码
// 使用组件
<Hello name="jack" age="20" />
javascript 复制代码
// 定义组件 props包含{name:'jack',age:'20'}
class Hello extends Component {
  render() {
    return <div>接收到的数据:{this.props.age}</div>;
  }
}

总结:

  • props 是实现组件通讯的关键,它通过使用组件绑定属性,组件内部使用 props 来传值。

3. 组件通讯-props 注意事项

知道 props 是单项数据流只读,但是可以传递任意数据。

大致步骤:

  • 知道什么是单向数据流
  • 知道 props 可以传递什么数据

具体内容:

  1. 知道什么是**单向数据流**?
    • 单向数据流,是从上到下的,自顶而下,数据流。
    • 好比:河流,瀑布,只能从上往下流动,上游污染下游受影响,但是下游不能影响上游。
    • 父组件传递数据给子组件,父组件更新数据子组件自动接收更新后数据,当是子组件是不能修改数据的。
  2. props 可以传递什么数据?任意
    • 字符串
    • 数字
    • 布尔
    • 数组
    • 对象
    • 函数
    • JSX (插槽)

总结:

  • props 传递数据是单向的,可以传递任意格式的数据。

4. 组件通讯-父传子方式

通过 props 将父组件的数据传递给子组件

大致步骤:

  • 父组件提供要传递的 state 数据
  • 给子组件标签添加属性,值为 state 中的数据
  • 子组件中通过 props 接收父组件中传递的数据

具体代码:

① 父组件提供要传递的 state 数据

javascript 复制代码
class Parent extends React.Component {
  state = {
    money: 10000,
  };
  render() {
    return (
      <div>
        <h1>父组件:{this.state.money}</h1>
      </div>
    );
  }
}

② 给子组件标签添加属性,值为 state 中的数据

javascript 复制代码
class Parent extends React.Component {
  state = {
    money: 10000
  }
  render() {
    return (
      <div>
        <h1>父组件:{this.state.money}</h1>
+        <Child money={this.state.money} />
      </div>
    )
  }
}

③ 子组件中通过 props 接收父组件中传递的数据

javascript 复制代码
function Child(props) {
  return (
    <div>
      <h3>子组件:{props.money}</h3>
    </div>
  );
}

总结:

  • 父组件声明**state,在子组件标签通过属性绑定,在子组件中通过props**使用。

5. 组件通讯-子传父方式

通过 props 将子组件的数据传递给父组件

大致步骤:

  • 父组件提供回调函数,通过 props 传递给子组件
  • 子组件调用 props 中的回调函数,函数可传参
  • 父组件函数的参数就是子组件传递的数据

具体代码:

① 父组件

javascript 复制代码
class Parent extends React.Component {
  state = {
    money: 10000,
  };
  // 回调函数
  buyPhone = (price) => {
    this.setState({
      money: this.state.money - price,
    });
  };
  render() {
    const { money } = this.state;
    return (
      <div>
        <h1>父组件:{money}</h1>
        <Child money={money} buyPhone={this.buyPhone} />
      </div>
    );
  }
}

② 子组件

javascript 复制代码
const Child = (props) => {
  const handleClick = () => {
    // 子组件调用父组件传递过来的回调函数
    props.buyPhone(5000);
  };
  return (
    <div>
      <h3>子组件:{props.money}</h3>
      <button onClick={handleClick}>买手机</button>
    </div>
  );
};

总结:

  • 子组件如何传递数据给父组件?
    • 触发父组件传递的回调函数传入数据
  • 父组件如何接收子组件的数据?
    • 回调函数的参数是子组件传递的数据
  • 父组件数据更新后,传递给子组件的数据是否更新?
    • 自动更新

6. 组件通讯-兄弟组件通讯

通过状态提升思想完成兄弟组件数据通讯

大致步骤:

  • 状态提升思想是什么?
  • 演示通过状态提升完成兄弟组件通讯。

具体内容:

① 状态提升思想是什么?

  • 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态和修改状态的方法
  • 需要通讯的组件通过 props 接收状态和函数即可

② 参考代码

  • index.js
javascript 复制代码
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

// 导入两个子组件
import Jack from './Jack';
import Rose from './Rose';

// App 是父组件
class App extends Component {
  // 1. 状态提升到父组件
  state = {
    msg: '',
  };

  changeMsg = (msg) => {
    this.setState({ msg });
  };

  render() {
    return (
      <div>
        <h1>我是App组件</h1>
        {/* 兄弟组件 1 */}
        <Jack changeMsg={this.changeMsg}></Jack>
        {/* 兄弟组件 2 */}
        <Rose msg={this.state.msg}></Rose>
      </div>
    );
  }
}

// 渲染组件
ReactDOM.render(<App />, document.getElementById('root'));
  • Jack.js
javascript 复制代码
import React, { Component } from 'react';

export default class Jack extends Component {
  say = () => {
    // 修改数据
    this.props.changeMsg('you jump i look');
  };
  render() {
    return (
      <div>
        <h3>我是Jack组件</h3>
        <button onClick={this.say}>说</button>
      </div>
    );
  }
}
  • Rose.jsx
javascript 复制代码
import React, { Component } from 'react';

export default class Rose extends Component {
  render() {
    return (
      <div>
        <h3>我是Rose组件-{this.props.msg}</h3>
      </div>
    );
  }
}

7. 组件通讯-context 跨级组件通讯

掌握使用 context 实现跨级组件通讯

大致步骤:

  • 什么是跨级组件通讯?
  • context 怎么去理解?
  • 演示使用 context 完成跨级组件通讯。

具体内容:

什么是跨级组件通讯?

① 组件间相隔多层,理解成叔侄,甚至更远的亲戚。

② context 怎么去理解

  • 术语:上下文
  • 理解:一个范围,只要在这个范围内,就可以跨级组件通讯。(不需要 props 层层传递)

③ context使用方法

  • 创建上下文
javascript 复制代码
import { createContext } from 'react' // 引入创建上下文的方法
export default createContext(初始值) // 初始值会在找不到Provider提供者时生效
  • 使用上下文的Provider组件作为提供者
javascript 复制代码
import Context from './context'

function Parent () {
   
  return <Context.Provider value={context共享的值}>
  
        ....子孙组件
   </Context.Provider>
  
}
  • 使上下文的Consumer作为消费者
javascript 复制代码
import Context from './context'
function Child () {
  return <Context.Consumer>
    {
      value => JSX
    }
  </Context.Consumer>
}

创建上下文对象,上下文对象存在提供者和消费者,提供者提供数据,消费者消费数据

总结:

  • 使用**creatContext()** 创建一个上下文对象,包含:Provider Consumer 组件。
  • 使用 Provider包裹组件,value属性注入状态函数,被包裹组件下的任何组件可以使用。
  • 使用 **Consumer**消费 Provider提供的数据和函数,语法{value=>使用数据和函数}

8. props-children 属性

掌握 props 中 children 属性的用法

大致步骤:

  • props 中 children 属性代表什么?
  • props 中 children 属性的使用
  • 使用 props 中 children 属性 封装 **NavBar**组件

具体内容:

① props 中 children 属性代表什么?

  • 组件标签的子节点(标签之间的内容),可以是任意值(文本,React 元素,组件,函数)

② props 中 children 属性的使用

javascript 复制代码
// 定义组件
const Hello = (props) => {
  return <div>该组件的子节点:{props.children}</div>;
};
// 使用组件
<Hello>我是子节点</Hello>;

③ 使用 props 中 children 属性 封装 **NavBar**组件

javascript 复制代码
import React, { Component } from 'react';

const NavBar = (props) => {
  return <h3>&lt;&nbsp;{props.children}</h3>;
};

export default class App extends Component {
  render() {
    return (
      <>
        <NavBar>文章详情</NavBar>
        <NavBar>文章列表</NavBar>
        <NavBar>
          我的<span style={{ color: 'red' }}>点赞</span>
        </NavBar>
      </>
    );
  }
}

9. props-类型校验

校验接收的props的数据类型,增加组件的稳健性

大致步骤:

  • 理解props都是外来的,在使用的时候如果数据类型不对,很容易造成组件内部逻辑出错
  • 通过 prop-types 可以在创建组件的时候进行类型检查,更合理的使用组件避免错误

具体内容:

① 理解props都是外来的,在使用的时候如果数据类型不对,很容易造成组件内部逻辑出错

javascript 复制代码
// 开发者A创建的组件
const List = props => {
  const arr = props.colors
  const list = arr.map((item, index) => <li key={index}>{item.name}</li>)
	return (
		<ul>{list}</ul>
	)
}

// 开发者B去使用组件
<List colors={19} />

报错:

  • TypeError: arr.map is not a function

② 通过 prop-types 可以在创建组件的时候进行类型检查,更合理的使用组件避免错误

  • 安装**yarn add prop-types(脚手架创建自带这个包)**
  • 导入**import PropTypes from 'prop-types'**
  • 使用 **组件名.propTypes = { 'props属性':'props校验规则' } 进行类型约定,PropTypes**包含各种规则
javascript 复制代码
import PropTypes from 'prop-types'

const List = props => {
  const arr = props.colors
  const lis = arr.map((item, index) => <li key={index}>{item.name}</li>)
  return <ul>{lis}</ul>
}

List.propTypes = {
  // props属性:校验规则
  colors: PropTypes.array
}

总结:

  • 在提供组件的时候,props校验可以让组件使用更加准确。

10. props-类型校验常见类型

了解react组件props校验的常见规则

大致步骤:

  • 了解常见的校验规则
  • 演示校验规则的使用

具体内容:

  • 了解常见的校验规则

    1. 常见类型:array、bool、func、number、object、string
    2. React元素类型:element
    3. 必填项:isRequired
    4. 特定结构的对象:shape({})
  • 演示校验规则的使用

javascript 复制代码
const Demo = (props) => {
  return <div>Demo组件</div>
}
Demo.propTypes = {
  // 常见类型
  optionalFunc: PropTypes.func,
  // 常见类型+必填
  requiredFunc: PropTypes.func.isRequired,
  // 特定结构的对象
  optionalObjectWithShape: PropTypes.shape({
    color: PropTypes.string,
    fontSize: PropTypes.number
  })
}

总结:

  • 通过**PropTypes**可以得到常见的校验规则

11. props-默认值

给组件的props提供默认值

大致步骤:

  • 知道 **defaultProps**的作用?
  • 演示如何设置props的默认值
  • 新版react推荐使用参数默认值来实现

具体内容:

① 知道 **defaultProps**的作用

  • 给组件的props设置默认值,在未传入props的时候生效

② 如何设置props的默认值参考代码

javascript 复制代码
// 分页组件
const Pagination = (props) => {
  return <div> pageSize的默认值:{props.pageSize}</div>
}
// 设置默认值
Pagination.defaultProps = {
	pageSize: 10
}
// 使用组件
<Pagination />

③ 新版react推荐使用**参数默认值**来实现

javascript 复制代码
// 分页组件
const Pagination = ({pageSize = 10}) => {
  return <div> pageSize的默认值:{pageSize}</div>
}
// 使用组件
<Pagination />

总结:

  • **组件名称.defaultProps**可以设置props属性默认值,未传的时候使用
  • 新版 react 更推荐 参数默认值 来实现

12. props-静态属性写法

知道在类组件中如何设置 类型校验 和 默认值

大致步骤:

  • 类的静态属性写法和如何访问它
  • 类组件中 propTypes defaultProps 的使用代码参考

具体内容:

① 类的静态属性写法和如何访问它

  • 实例属性需要实例化后,通过实例访问
  • 静态属性,可以通过类直接访问
javascript 复制代码
class Person {
  // 实例成员
  constructor (name, age) {
    this.name = name
    this.age = age
  }
  // 实例方法
  sayHi () {
    console.log('Hi')
  }

  // static 关键字: 静态成员
  static aa = 'bb'
}

// 实例成员: 通过实例调用的属性或者方法,叫做实例成员(属性或者方法)
const p = new Person('刘建超', 20)
console.log(p.age)
p.sayHi()

// 静态成员: 通过类或者构造函数本身才能访问的属性或者方法
Person.username = '人'
console.log(p.username) //undefined
console.log(Person.username) //人
console.log(Person.aa) // bb

② 类组件中 **propTypes defaultProps**的使用代码参考

javascript 复制代码
class Demo extends Component {
  // 校验
  static propTypes = {
    colors: PropTypes.array,
    gender: PropTypes.oneOf(['男', '女']).isRequired
  }
  // 默认值
  static defaultProps = {
	gender: '男'
  }
  
  render() {
    return <div>Demo组件</div>
  }
}

总结:

  • 在类组件中通过 static propTypes = {} 定义props校验规则 **static defaultProps = {}**定义props默认值
相关推荐
biter00888 分钟前
opencv(15) OpenCV背景减除器(Background Subtractors)学习
人工智能·opencv·学习
车轮滚滚__19 分钟前
uniapp对接unipush 1.0 ios/android
笔记
用户305875848912525 分钟前
Connected-react-router核心思路实现
react.js
Code哈哈笑1 小时前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
QQ同步助手2 小时前
如何正确使用人工智能:开启智慧学习与创新之旅
人工智能·学习·百度
流浪的小新2 小时前
【AI】人工智能、LLM学习资源汇总
人工智能·学习
A懿轩A3 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
云边有个稻草人3 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
南宫生11 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
sanguine__11 小时前
Web APIs学习 (操作DOM BOM)
学习