React组件进阶

一、 组件通讯介绍

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

二、组件的props

2.1 基本使用

  • 组件是封闭的,要接受外部数据应该通过props来实现
  • props的作用:接收传递给组件的数据

  • 传递数据:给组件标签添加属性
<App name="Mike" age={23} />
  • 接收数据:函数组件通过 参数 props接收数据,类组件通过 this.props接收数据
    • 函数组件获取数据
function App(props) {
  console.log(props)
  return <div>接收到的数据:{props.name}</div>
}

ReactDOM.render(<App name="Mike" age={23} />, document.getElementById('root'))
  • 类组件获取数据
class App extends React.Component {
  render() {
    return <div>接收到的数据:{this.props.age}</div>
  }
}

ReactDOM.render(<App name="Mike" age={23} />, document.getElementById('root'))

2.2 特点

  • 可以给组件传递任意类型的数据(包括函数与JSX)
  • props是只读属性,不能对值进行修改
  • 注意:使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props,其他的地方是可以拿到的
class App extends React.Component {
  constructor(props) {
    super(props)
    console.log(this.props)
  }
  render() {
    return <div>接收到的数据:{this.props.age}</div>
  }
}

三、组件通讯的三种方式

3.1 父组件传递数据给子组件

  • 父组件提供要传递的state数据
  • 给子组件标签添加属性,值为state中的数据
  • 子组件中通过props接收父组件中传递的数据
import React from 'react'
import ReactDOM from 'react-dom'

class Parent extends React.Component {
  state = { Name: 'Boyi' }
  render() {
    return (
      <div>
        传递数据给子组件:
        <Child name={this.state.Name} />
      </div>
    )
  }
}

function Child(props) {
  return <div>子组件接收到的数据:{props.name}</div>
}

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

3.2 子组件传递数据给父组件

  • 利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数
  • 父组件提供一个回调函数,用来接收数据
  • 将该函数作为属性的值,传递给子组件
class Parent extends React.Component {
  getChildMsg = msg => {
    console.log('接收到子组件数据', msg)
  }
  render() {
    return (
      <div>
        子组件:
        <Child getMsg={this.getChildMsg} />
      </div>
    )
  }
}
  • 子组件通过props调用回调函数
class Child extends React.Component {
  state = { childMsg: 'React' }
  handleClick = () => {
    this.props.getMsg(this.state.childMsg)
  }
  render() {
    return <button onClick={this.handleClick}>点我,给父组件传值</button>
  }
}

3.3 兄弟组件传递

  • 将共享状态(数据)提升到最近的公共父组件中,由公共父组件管理这个状态
  • 这个称为状态提升
  • 公共父组件职责:1. 提供共享状态 2.提供操作共享状态的方法
  • 要通讯的子组件只需要通过props接收状态或操作状态的方法

示例demo

  • 定义布局结构,一个Counter里面包含两个子组件,一个是计数器的提示,一个是按钮
import React from 'react'
import ReactDOM from 'react-dom'

class Counter extends React.Component {
  // 提供共享状态
  state = {
    count: 10
  }

  // 提供共享方法,使用箭头函数,避免this指向问题
  onIncrement = res => {
    this.setState({
      count: this.state.count + 1
    })
  }
  render() {
    return (
      <div>
        {/* 把状态保存在第一个子组件 */}
        <Child1 count={this.state.count} />
        {/* 把共享方法提供给第二个子组件 */}
        <Child2 onIncrement={this.onIncrement} />
      </div>
    )
  }
}

class Child1 extends React.Component {
  render() {
    // 通过props获取状态
    return <h1>计数器:{this.props.count}</h1>
  }
}

class Child2 extends React.Component {
  handleClick = () => {
    // 调用,执行父组件里面的onIncrement函数
    this.props.onIncrement()
  }
  render() {
    return <button onClick={this.handleClick}>+1</button>
  }
}

ReactDOM.render(<Counter />, document.getElementById('root'))

四、Context

如果出现层级比较多的情况下(例如:爷爷传递数据给孙子),我们会使用Context来进行传递

作用: 跨组件传递数据

使用步骤

import React from 'react'
import ReactDOM from 'react-dom'

// 1、创建context得到两个组件
const { Provider, Consumer } = React.createContext()

class App extends React.Component {
  render() {
    return (
      // 2、利用Provider中的value属性来传递数据
      <Provider value="helloWorldzzz">
        <div className="App">
          <Node />
        </div>
      </Provider>
    )
  }
}

class Node extends React.Component {
  render() {
    return (
      <div>
        <Child></Child>
      </div>
    )
  }
}

const Child = props => {
  return (
    // 3. 通过Consumer中回调函数的data值来接收传递的值
    <div className="child">
      <Consumer>
        {data => <span>data参数表示接受到的数据 -- {data}</span>}
      </Consumer>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

小结

  • 如果两个组件相隔层级比较多,可以使用Context实现组件通讯
  • Context提供了两个组件:Provider 和 Consumer
  • Provider组件: 用来提供数据
  • Consumer组件: 用来消费数据

五、props进阶

5.1 children属性

  • children属性: 表示组件标签的子节点,当组件标签有子节点时,props就会有该属性
  • children属性普通的props一样,值可以使任意值(文本、react元素、组件、甚至是函数)
import React from 'react'
import ReactDOM from 'react-dom'

function Hello(props) {
  console.log(props)
  return <div>组件的子节点:{props.children}</div>
  // 我是子节点
}

ReactDOM.render(<Hello>我是子节点</Hello>, document.getElementById('root'))

5.2 props校验

  • 对于组件来说,props是外来的,无法保证组件使用者传入什么格式的数据,简单来说就是组件调用者可能不知道组件封装着需要什么样的数据
  • 如果传入的数据不对,可能会导致报错
  • 关键问题:组件的使用者不知道需要传递什么样的数据
  • props校验:允许在创建组件的时候,指定props的类型、格式等
Hello.propTypes = {
  // 约定colors属性为array类型
  // 当类型不对时,会报出明确错误
  colors: PropTypes.array
}
  • 作用:捕获使用组件时因为props导致的错误,给出明确的错误提示,增加组件的健壮性

在这里插入图片描述

使用步骤

  • 安装包 prop-types (yarn add prop-types | npm i prop-types)
  • 导入prop-types
  • 使用组件名.propTypes={} 来给组件的props添加校验规则
  • 校验规则通过PropTypes对象来指定
import React from 'react'
import ReactDOM from 'react-dom'

import PropTypes from 'prop-types'

function Hello(props) {
  console.log(props)
  const arr = props.colors
  const lis = arr.map((item, index) => <li key={index}>{item}</li>)
  return <ul>{lis}</ul>
}

Hello.propTypes = {
  // 约定colors属性为array类型
  // 当类型不对时,会报出明确错误
  colors: PropTypes.array
}

ReactDOM.render(<Hello colors={12} />, document.getElementById('root'))

5.3 常见的约束规则

  • 创建的类型: array、bool、func、number、object、string
  • React元素类型:element
  • 必填项:isRequired
  • 特定结构的对象: shape({})
  • 更多的约束规则
App.propTypes = {
  a: PropTypes.number, //数值类型
  fn: PropTypes.func.isRequired, //函数类型且为必填项
  tag: PropTypes.element, //React元素(element)
  filter: PropTypes.shape({
    //特定对象结构
    name: PropTypes.string,
    price: PropTypes.number
  })
}

5.4 props的默认值

  • 组件.defaultProps来设置
  • 场景:分页组件 -> 每页显示条数
import React from 'react'
import ReactDOM from 'react-dom'

import PropTypes from 'prop-types'

function App(props) {
  return (
    <div>
      <h1>此处展示props的默认值:{props.pageSize}</h1>
    </div>
  )
}

//  设置默认值,当没有传入值时,使用默认值,当有值传入时,使用传入的值
App.defaultProps = {
  pageSize: 10
}

ReactDOM.render(<App pageSize={20} />, document.getElementById('root'))

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值