React学习two
1. 使用props组件通讯
父组件->子组件
- 父组件提供需要传递的state数据
- 给子组件标签添加属性,,值为state中的数据
- 子组件中通过props接收父组件中传递的数据
子组件->父组件
- 父组件提供回调函数。用于接收数据
- 将该函数作为属性值,传递给子组件
- 子组件通过props调用回调函数
import React from 'react';
import ReactDOM from 'react-dom';
class Parent extends React.Component {
state = {
data: ''
}
//父组件提供回调函数
getChilfMsg = data => {
console.log("接受子组件传递的数据", data)
this.setState({
data: data
})
}
render() {
return (
<div>
这是父组件:
{this.state.data}
<Child getMsg={this.getChilfMsg}></Child>
</div>)
}
}
class Child extends React.Component {
state = {
msg: '我是子组件'
}
handleClick = () => {
//子组件调用父组件中传递的回调函数
this.props.getMsg(this.state.msg)
}
render() {
return (
<div>
这是子组件:
<button onClick={this.handleClick}>点击</button>
</div>)
}
}
//渲染组件
ReactDOM.render(<Parent></Parent>, document.getElementById('root'))
兄弟组件
- 提供一个组件作为这两个兄弟组件的父组件
- 通过父组件->子组件通讯的方式进行通讯
2.使用Context跨越多层组件传值
const { Provider, Consumer } = React.createContext()
class AAl extends React.Component {
render() {
return (
<Provider value="我是符组件的值">
<div>
这是父组件:
<Ac></Ac>
</div>
</Provider>
)
}
}
const Ac=props=>{
return(
<Consumer>
{data => <span>dsdasdas {data}</span>}
</Consumer>
)
}
//渲染组件
ReactDOM.render(<AAl/>, document.getElementById('root'))
3.props深入
Children属性
- 表示组件标签的子节点,当组件标签有子节点时,props就会有该属性
- 值可以是任意值(文本、React元素、组件、 函数)
//可以是标签
ReactDOM.render(<Parent><p>我是子节点</p></Parent>, document.getElementById('root'))
//可以是函数
ReactDOM.render(<Parent>{() => { console.log("函数子节点") }}</Parent>, document.getElementById('root'))
- 通过props.children调用
props的校验
-
允许在创建组件时,就指定props的类型、格式等
-
可以捕获使用组件时导致的错误
-
使用校验步骤
1.安装prop-types
npm i prop-types
2.导入prop-types包
3.使用
组件名.propTypes={}
来给组件的props添加校验规则4.校验规则通过
导入的prop-types对象
向来指定
import React from 'react';
import ReactDOM from 'react-dom';
// 2.导入prop-types包
import type from 'prop-types'
const Acs = props => {
const App = props.colors
const list = App.map((item, index) => <li key={index}>{item}</li>)
return (
<ul>{list}</ul>
)
}
//3.使用 组件名.propTypes={} 来给组件的props添加校验规则
Acs.propTypes={
//4.指定校验规则
colors: type.array
}
//渲染组件
ReactDOM.render(<Acs colors={[1,2]}></Acs>, document.getElementById('root'))
约束规则
- 常见类型 arry、bool、func、number、object、string
- 必填项可以使用isRequired来限制
- 指定结构的对象可以使用shape({ })
props默认值
通过组件名.defaultProps
来设置默认值
在未传入props时生效
Acs.defaultProps={
colors:[1,2]
}
4.组件生命周期
只有类组件才有生命周期
生命周期的三个阶段
创建阶段
- 执行时机:页面加载时
- 执行顺序
constructor()->render()->componetDidMount
钩子函数 | 触发时机 |
---|---|
constructor | 创建组件时,最先执行 |
render | 每次组件渲染时都会触发 |
componetDidMount | 组件挂载结束后 |
更新阶段
更新阶段也就是执行**render()**渲染页面的时候。
- 执行时机:
1.执行setState()
2.执行firceUpdate()
3.组件接受到新的props - 执行顺序
render()->componetDidUpdate
注意:在componetDidMount中如果要调用setState()更新状态,必须要放到一个if条件中。条件是判断前后数据内容是否一致
原因:调用setState()会调用render()重新渲染页面,render()执行结束后又会调用componetDidMount。在componetDidMount里面仍然调用了setState(),导致递归调用。
卸载阶段
通过componetWillUnmount在组件从页面消失时。执行清理操作
5.render-porps和高阶组件
使用render-props模式实现获取鼠标坐标
import React from 'react';
import ReactDOM from 'react-dom';
import type from 'prop-types'
class Mouse extends React.Component {
state = {
x: 0,
y: 0
}
move = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
componentDidMount() {
window.addEventListener('mousemove', this.move)
}
render() {
return (
//使用children属性
this.props.children(this.state)
//使用render属性
// this.props.render(this.state)
)
}
}
//校验必须又children
Mouse.propTypes={
chileren:type.func.isRequired
}
class App extends React.Component {
render() {
return (
<div>
//使用render属性实现
{/* <Mouse render={mouse=>{return <p>x:{mouse.x}y:{mouse.y}</p>}}></Mouse> */
//使用children属性实现
<Mouse>
{
mouse => {
return <p>x:{mouse.x}y:{mouse.y}</p>
}
}
</Mouse>
}
</div>
)
}
}
//渲染组件
ReactDOM.render(<App ></App>, document.getElementById('root'))
高阶组件的使用
- 创建一个函数,名称约定以with开头
- 指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
- 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
- 在该组件中,渲染参数组件,同时将状态通过prop传递参数组件
- 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
import React from 'react';
import ReactDOM from 'react-dom';
import type from 'prop-types'
function WithMouse(Wrapped) {
//在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
class Mouse extends React.Component {
state = {
x: 0,
y: 0
}
move = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
componentDidMount() {
window.addEventListener('mousemove', this.move)
}
//在该组件中,渲染参数组件,同时将状态通过prop传递参数组件
render() {
return <Wrapped {...this.state}></Wrapped>
}
}
return Mouse
}
//测试高阶组件
const Position = props => {
return (<p>
x:{props.x},y:{props.y}
</p>)
}
//获取增强后的组件
// 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
const MousePosition = WithMouse(Position)
class App extends React.Component {
render() {
return (<div>
<h1>高阶</h1>
<MousePosition></MousePosition>
</div>
)
}
}
//渲染组件
ReactDOM.render(<App></App>, document.getElementById('root'))
displayName属性
用于设置调试信息。给函数中的类组件设置名字