内容:状态机、组件通信、生命周期、DOM节点操作
日期:2020-09-14
一、状态机setState是一个异步操作
setState用来修改state中的初始状态,但是它异步操作,不能在setState之后马上获取到最新的数据。可以使用setState的第二个参数来获取到最新的数据
setState(要修改的数据对象,()=>{...})
在第二个参数(回调函数)中可以获取到state中最新的数据。
示例代码:
import React, { Component } from 'react'
export default class State extends Component {
state = {
num :100
}
addNum(){
var n = this.state.num;
n++;
this.setState({ num : n },()=>{
console.log(this.state.num,1111111111)//在回调函数中可以获取到state中最新的数据
})
console.log(this.state.num,222222222222)//此时获取到的数据不是最新的
}
render() {
return (
<div>
<h2>数量:{ this.state.num }</h2>
<button onClick={ ()=>this.addNum() }>点击增加</button>
</div>
)
}
}
二、组件通信
1.父子组件
在父组件使用子组件时,通过自定义属性进行数据的传递,在子组件中通过props来接收。
(1)父组件
import React, { Component } from 'react'
import Child from './Child'
export default class Parent extends Component {
state = {
msg : '天道酬勤'
}
render() {
return (
<div>
<h1>这是父组件</h1>
<hr/>
<Child data={this.state.msg} />
</div>
)
}
}
(2)子组件
import React, { Component } from 'react'
class Child extends Component {
render() {
return (
<div>
<h2>这是子组件</h2>
{/* 通过this.props来获取父组件传递的数据 */}
<p>父组件的内容:{ this.props.data }</p>
</div>
)
}
}
export default Child;
2.子父组件
使用自定义事件来实现子父组件通信
在父组件使用子组件时,传递一个自定义事件,用来让子组件触发或者进行数据的传递
import React, { Component } from 'react'
import Child from './Child'
export default class Parent extends Component {
state = {
msg : '天道酬勤',
str:''
}
getStr(e){
this.setState({ str:e })
}
render() {
return (
<div>
<h1>这是父组件</h1>
<p>子组件:{ this.state.str }</p>
<hr/>
<Child data={this.state.msg} sendStr={ (str)=>this.getStr(str) } />
</div>
)
}
}
在子组件中,通过this.props.自定义事件名 来触发父组件的函数并传递参数
import React, { Component } from 'react'
class Child extends Component {
send(){
console.log(this)
//调用父组件传递的函数
this.props.sendStr('这是子组件的数据');
}
render() {
return (
<div>
<h2>这是子组件</h2>
{/* 通过this.props来获取父组件传递的数据 */}
<p>父组件的内容:{ this.props.data }</p>
<button onClick={ ()=>this.send() }>反馈数据</button>
</div>
)
}
}
export default Child;
3.非父子组件
(1)设置一个公用容器
创建/src/bus.js,并引入events类中的EventEmitter事件监听器
const EventEmitter = require('events');
const MyEvent = new EventEmitter();
export default MyEvent;
(2)在项目启动文件中进行Component原型的挂载
/src/index.js
import React,{ Component } from 'react';
import bus from './bus'
Component.prototype.bus = bus;//将容器挂载到Component的原型上
(3)页面组件中使用
①数据发生端
this.bus.emit('事件名称','要传递的数据')
②数据接收端
constructor(){
super();
this.bus.on('事件名称',(形参)=>{
...
})
}
三、生命周期
只有类组件才有生命周期,函数组件没有生命周期。
图示:
页面渲染期:
constructor 构造函数
UNSAFE_componentWillMount 组件将要挂载
render 组件渲染
componentDidMount 组件挂载完成
页面更新期:
UNSAFE_componentWillReceiveProps 子组件将要接收父组件传递的数据(数据在父组件中改变,然后传递给子组件时会触发此钩子函数)
shouldComponentUpdate 组件是否要更新数据(返回布尔值,true更新,false不更新)
render 组件渲染更新
UNSAFE_componentWillUpdate 组件将要更新,shouldComponentUpdate返回true时才执行
componentDidUpdate 组件更新完成,shouldComponentUpdate返回true时才执行
页面销毁期:
componentWillUnmount 组件将要销毁,组件不再显示时
四、state和props混用
state是页面组件的初始数据(当前组件可以对state中的数据进行任意修改)
props是父组件传递给子组件的数据(子组件只能读取props中的数据,不能直接修改)
子组件中的state要根据父组件传递过来的数据进行同步时,会存在一个数据不同步的问题
父组件:
import React, { Component } from 'react'
import Item from './Item'
export default class Home extends Component {
state = {
num:100
}
componentDidMount(){
console.log('home组件挂载完成')
this.setState({
num:50
})
}
render() {
return (
<div>
<h1>home页面</h1>
<hr/>
<Item pdata={ this.state.num }></Item>
</div>
)
}
}
子组件:
import React, { Component } from 'react'
export default class Item extends Component {
state = {
num:0
}
componentDidMount(){
console.log('item组件挂载完成')
this.setState({
num:this.props.pdata//此时num的数据是父组件没有修改之前的数据,num是100
})
}
render() {
return (
<div>
<h2>item页面</h2>
<p>home组件的数据:{ this.state.num }</p>
</div>
)
}
}
为了解决state和props混用时出现的数据不同步问题,我们要把setState第一个参数写成一个函数,在这个函数中的第一个参数是当前组件的state数据,第二个参数是父组件传递过来的最新数据。
import React, { Component } from 'react'
export default class Item extends Component {
state = { num:0 }
componentDidMount(){
console.log('item组件挂载完成')
this.setState(function(state,props){
state.num = props.pdata;
})
}
render() {
return (
<div>
<h2>item页面</h2>
<p>home组件的数据:{ this.state.num }</p>
</div>
)
}
}
setState的参数
可以是一个对象
可以是一个对象+一个回调函数
可以是一个函数
五、DOM节点操作
1.字符串
可以给标签添加ref属性,在组件挂载完成后就可以通过this.refs来DOM节点的操作
export default class Home extends Component {
render() {
return (
<div>
<h1 ref="myh1">home页面</h1>
</div>
)
}
componentDidMount(){
this.refs.myh1.innerHTML = '向英雄致敬'
}
}
2.回调函数
ref属性可以用在普通标签上,也可以使用在子组件上,通过DOM节点操作来实现组件之间通信。
import React, { Component } from 'react'
import Child from './Child'
export default class Home extends Component {
render() {
return (
<div>
{/* <Child ref="mychild"/> */}
<Child ref={(e)=>this.setChild(e)} />
</div>
)
}
componentDidMount(){
// this.refs.myh1.innerHTML = '向英雄致敬'
// console.log(this.refs)
}
setChild(el){
//此时el就是子组件
// console.log(el)
el.setState({
msg:'向英雄致敬'
})
}
}
3.createRef API
react中给提供了一个createRef API方法,用它也可以来实现DOM节点操作
在构造函数中通过React.createRef来创建一个空的容器
constructor(){
super();
this.childEl = React.createRef();//this.childEl {current:null}
}
在页面中使用标签或者子组件时,通过ref进行赋值
<Child ref={ this.childEl } />
此时this.childEl.current就是子组件
本文详细介绍了React开发中的关键概念,包括状态机setState的异步特性,组件间的通信(父子、子父、非父子组件间),生命周期的各个阶段,以及如何在React中操作DOM节点,包括字符串、回调函数和createRef API的使用。


被折叠的 条评论
为什么被折叠?



