1.组件通讯介绍
- * 组件是*独立且封闭*的单元(为了复用,避免冲突),默认情况下,只能使用组件自己的数据
- * 在组件化过程中,通常会将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能
- * 而在这个过程中,多个组件之间不可避免的要共享某些数据
- * 为了实现这些功能,就需要**打破组件的独立封闭性**,让其与外界沟通。这个过程就是**组件通讯**。
总结:*组件中的状态是私有的*,也就是说,组件的状态只能在组件内部使用,无法直接在组件外使用
2.props基本使用
- 函数组件获取props
// 接收数据:
// props 的值就是:{ name: 'jack', age: 19 }
function Hello(props) {
return (
<div>接收到数据:{props.name}</div>
)
}
// 传递数据:
// 可以把传递数据理解为调用函数 Hello,即:Hello({ name: 'jack', age: 19 })
<Hello name="jack" age={19} />
<div id="" name=""></div>
- 类组件获取props
// 接收数据:
// class 组件需要通过 this.props 来获取
// 注意:this.porps 属性名是固定的!!!
class Hello extends Component {
render() {
return (
<div>接收到的数据:{this.props.age}</div>
)
}
}
// 传递数据:
<Hello name='jack' age={19} />
3.props注意点
1. **props 是只读对象**,也就是说:只能读取对象中的属性,无法修改
**单向数据流**,也叫做:自顶而下(自上而下)的数据流
表示:父组件中的数据可以通过 props 传递给子组件,并且,当父组件中的数据更新时,子组件就会自动接收到最新的数据
类比:就像瀑布的水一样只能从上往下流动,并且,当上游的水变浑浊,下游的水也会受到影响
2.可以传递任意数据(数字 字符串 布尔类型 数组 对象 函数 jsx)
4.组件通讯-----父传子
import React, { Component } from 'react'
// 函数子组件
const Fn=(props)=>{
console.log('函数组件接收到的值:',props);
return (
<div>
<h2>函数子组件</h2>
<p>函数组件接收到的值:{props.money}</p>
<p>函数组件接收到的值:{props.changeMoney()}</p>
</div>
)
}
// 类子组件
class Fn1 extends Component{
render(){
console.log("类子组件接收到的值:",this.props);
return (
<div>
<h2>类子组件</h2>
<p>类组件接收到的值:{this.props.money}</p>
<div>
{this.props.html}
</div>
</div>
)
}
}
// 父组件
class App extends Component {
// 传递灵活的变量
state={
money:10
}
// 传递一个函数
changeMoney=()=>{
console.log(this);
return 123
}
// 传递一个jsx
html=(<p>123</p>)
render() {
return (
<div >
<h2>父组件</h2>
<hr/>
<Fn money="100000" text={this.state.money} changeMoney={this.changeMoney}/>
<Fn1 money="120000" html={this.html}/>
</div>
)
}
}
export default App
5.组件通讯--------子传父
*将父组件的方法传递给子组件,子组件传值、调用传递过来的方法
import React, { Component } from 'react'
// 函数子组件
const Fn=(props)=>{
console.log('函数组件接收到的值:',props);
const changeMoney=()=>{
props.changeMoney(1e8)
}
return (
<div>
<h2>函数子组件</h2>
<p>函数组件接收到的值:{props.money}</p>
<button onClick={()=>props.changeMoney(100)}>调用父组件方法1</button>
<button onClick={changeMoney}>调用父组件方法2</button>
</div>
)
}
// 父组件
class App extends Component {
// 传递灵活的变量
state={
money:10
}
// 传递一个函数
changeMoney=(chileData)=>{
this.setState({
money:chileData
})
}
render() {
return (
<div >
<h2>父组件</h2>
<hr/>
<Fn money={this.state.money} text={this.state.money} changeMoney={this.changeMoney}/>
</div>
)
}
}
export default App
6.组件通讯-----兄弟组件
将兄弟组件中需要的状态放置在父组件中,然后父传子,或子穿父。
import React, { Component } from 'react'
// 兄弟1
const Brother1=(props)=>{
return(
<div>
<h2>兄弟1</h2>
<h3>{props.count}</h3>
<button onClick={()=>{props.changecount(3)}}>修改count</button>
</div>
)
}
// 兄弟2
const Brother2=({count})=>{
return(
<div>
<h2>兄弟2</h2>
<h3>{count}</h3>
</div>
)
}
// 兄弟父组件
export default class App extends Component {
state={
count:0
}
changeCount=(data)=>{
this.setState({
count:data
})
}
render() {
return (
<div>
<h2>父</h2>
<hr></hr>
<Brother1 count={this.state.count} changecount={this.changeCount}/>
<Brother2 count={this.state.count}/>
</div>
)
}
}
7.组件通讯-------跨多级组件(context)
实现方式:使用 Context 来实现跨组件传递数据
Context 上下文,可以理解一个范围,只要在这个范围内,就可以直接跨组件传递数据
核心代码
// 0 导入创建 context 的函数
import { createContext } from 'react'
// 1 创建 Context 对象
// createContext 的返回值是一个 对象
// 对象中包含了两个组件,分别是: Provider 状态的提供者组件(提供状态) Consumer 状态的消费者组件(使用状态)
const { Provider, Consumer } = createContext()
// 2 使用 Provider 组件包裹整个应用,并通过 value 属性提供要共享的数据
<Provider value="blue">
<div className="App">
<Node />
</div>
</Provider>
// 3 使用 Consumer 组件接收要共享的数据
<Consumer>
{color => <span>data参数表示接收到的数据 -- {color}</span>}
</Consumer>
案例:(将contex单独创建一个js文件,导出调用)
context.js
import { createContext } from "react";
// 创建跨多级组件通信的context对象
const { Provider, Consumer } = createContext();
export { Provider, Consumer };
跨多级.jsx
import React, { Component } from 'react'
import {Provider,Consumer} from './context/context-obj'
// 孙子组件
class SubChild extends Component{
getApp=(data)=>{
console.log('jieshou',data);
}
render(){
return (
<div>
<h2>孙子组件</h2>
<Consumer>
{(data)=>
<h4>{data.name}:{data.age}</h4>
}
</Consumer>
<Consumer>
{this.getApp}
</Consumer>
</div>
)
}
}
// 子组件
class Child extends Component{
render(){
return (
<div>
<h2>子组件</h2>
<hr/>
<SubChild/>
</div>
)
}
}
// 父组件
export default class App extends Component {
state={
// 共享数据
obj:{
name:'cc',
age:18
}
}
render() {
return (
<Provider value={this.state.obj}>
<h2>父组件</h2>
<hr/>
<Child/>
</Provider>
)
}
}