Front-end/react/5.组件进阶.md

295 lines
7.3 KiB
Markdown
Raw Permalink Normal View History

2023-10-19 02:19:45 -04:00
# 组件通讯
多组件之间共享通讯
## props接收传递给组件的数据
传递数据:给组件标签添加属性
函数组件 props
```html
const HelloProps = (props)=>{
console.log(props)
return (
<div>props:{props.name}</div>
)
}
ReactDOM.render(<HelloProps name= "hua"/>,document.getElementById('root'))
```
类组件 this.props
```html
class HelloProps extends React.Component{
render(){
return (<div>props:{this.props.name},{this.props.role}</div>)
}
}
ReactDOM.render(<HelloProps name= "hua" role="shi"/>,document.getElementById('root'))
```
## 组件特点
1. 可以是任意值
```html
class HelloProps extends React.Component{
render(){
console.log(this.props)
return (<div>props:{this.props.name},{this.props.role} {this.props.tag}</div>)
}
}
ReactDOM.render(<HelloProps name= "hua" role="shi" age = {19}
colors = {['red','green','blue']}
fn={()=>console.log('我可以传函数')}
tag={<p>jsx</p>}
/>,document.getElementById('root'))
```
2. 只读
3. 在使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props
```html
class HelloProps extends React.Component{
constructor(props){
super(props)
console.log(this.props)
}
render(){
console.log(this.props)
return (<div>props:{this.props.name},{this.props.role} {this.props.tag}</div>)
}
}
ReactDOM.render(<HelloProps name= "hua" role="shi" age = {19}
colors = {['red','green','blue']}
fn={()=>console.log('我可以传函数')}
tag={<p>jsx</p>}
/>,document.getElementById('root'))
```
## 通讯的三种方式
### 父组件传递给子组件
1. 父组件提供传递的state数据
2. 给子组件添加属性,值为state中的数据
3. 子组件中通过props接收父组件中传递的数据
```html
class Parent extends React.Component{
state = {lastName:'师'}
render(){
return (
<div className='parent'>
父组件:
<Child name = {this.state.lastName}/>
</div>
)
}
}
// 子组件
const Child = (props)=>{
return (
<div className='child'>
<p>子组件接收到父组件的数据 {props.name}</p>
</div>
)
}
ReactDOM.render(<Parent />,document.getElementById('root'))
```
### 子组件传递给父组件
利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数.
1. 父组件提供一个回调函数(用于接收数据)
2. 将改函数作为属性的值,传递给子组件
3. 子组件通过props调用回调函数
4. 将子组件的数据作为参数传递给回调函数
```html
class Parent extends React.Component{
state={
parentMsg:''
}
getChildMsg = data=>{
console.log('接收到子组件传递过来的数据',data)
this.setState({
parentMsg:data
})
}
render(){
return (
<div className='parent'>
父组件:{this.state.parentMsg}
<Child name = {this.getChildMsg}/>
</div>
)
}
}
// 子组件
class Child extends React.Component{
state = {
msg:"回调传递"
}
handleClick=()=>{
//
this.props.name(this.state.msg)
}
render(){
return (
<div className='child'>
<p>子组件发送到父组件</p><button onClick={this.handleClick}>点击</button>
</div>
)
}
}
ReactDOM.render(<Parent />,document.getElementById('root'))
```
## 兄弟组件间的通讯
将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
状态提升
公共父组件职责:1.提供共享状态2.提供操作共享状态的方法
要通讯的子组件只能通过props接收状态或者操作状态的方法
```html
class Counter extends React.Component{
state={
count:0
}
onIncrement=()=>{
this.setState({
count:this.state.count+1
})
}
render(){
return(
<div>
<Child1 count={this.state.count}></Child1>
<Child2 onIncrement={this.onIncrement}></Child2>
</div>
)
}
}
const Child1=(props)=>{
return <h3>计数器:{props.count}</h3>
}
const Child2=(props)=>{
return <button onClick = {()=>props.onIncrement()}>+1</button>
}
ReactDOM.render(<Counter />,document.getElementById('root'))
```
# Context跨组件传递数据
1. 使用React.createContext()创建Provider,Consumer
2. 使用Provide组件作为父节点
3. 设置value属性,表示要传递的数据
4. 调用Consumer组件来接收数据
```html
const { Provider, Consumer } = React.createContext();
class ContextApp extends React.Component {
render() {
return (
<Provider value='pink'>
<div className="app">
<Node />
</div>
</Provider>
)
}
}
const Node = props => {
return (
<div className="node">
<SubNode />
</div>
)
}
const SubNode = props => {
return (
<div className="subNode">
<Child />
</div>
)
}
const Child = props => {
return <div className="child" ><Consumer>{data=><span>我是子节点---{data}</span>}</Consumer></div>
}
```
# props深入
## children表示组件标签的子节点.当组件标签有子节点时,props就会有该属性.
children 属性与普通props一样,值可以是任意值(文本,React元素,组件,甚至是函数)
```html
class ChildProps extends React.Component{
render(){
console.log(this.props)
return (
<div><h2>组件标签的子节点{this.props.children}</h2></div>
)
}
}
ReactDOM.render(<ChildProps>传递到props的child</ChildProps>,document.getElementById('root'))
```
```html
class ChildProps extends React.Component{
render(){
console.log(this.props)
return (
<div><h2>组件标签的子节点</h2>{this.props.children}</div>
)
}
}
const Test = ()=> <button>组件按钮</button>
ReactDOM.render(<ChildProps><Test/><p>传递到props的child</p></ChildProps>,document.getElementById('root'))
```
函数
```html
class ChildProps extends React.Component{
render(){
this.props.children()
console.log(this.props)
return (
<div><h2>组件标签的子节点</h2></div>
)
}
}
ReactDOM.render(<ChildProps>{()=>console.info("这是一个函数")}</ChildProps>,document.getElementById('root'))
```
## prop 校验
1. 安装prop-types (npm i prop-types 或者 yarn add prop-types)
2. 导入prop-types包
3. 使用组件名.propTypes={}来给组件的props添加校验规则
4. 校验规则通过PropTypes对象指定
```html
import React from "react"
import PropTypes from "prop-types"
class PropCheck extends React.Component{
render(){
const arr = this.props.colors
console.info(arr)
const lis = arr.map((item,index)=><li key={index}>{item}</li>)
return (
<ul>{lis}</ul>
)
}
}
PropCheck.protoTypes= {
colors:PropTypes.array
}
export default PropCheck
ReactDOM.render(<PropCheck colors = {['red','black']} />,document.getElementById('root'))
```
## prop 默认值
```html
class LPropCheck extends React.Component{
render(){
// const arr = this.props.colors
// console.info(arr)
// const lis = arr.map((item,index)=><li key={index}>{item}</li>)
// return (
// <ul>{lis}</ul>
// )
return <div><h2>test</h2>{this.props.colors}</div>
}
}
LPropCheck.propTypes= {
colors:PropTypes.array
}
LPropCheck.defaultProps= {
colors:["red"]
}
```