setState是异步更新
总结:
1.setState设计为异步,可以显著的提升性能
- 如果每次调用 setState都进行一次更新,那么意味着render函数会被频繁调用,界面重新染,这样效率是很低的;
- 最好的办法应该是获取到多个更新,之后进行批量更新;
2.如果同步更新了state,但是还没有执行render函数,那么state和props不能保持同步; - state和props不能保持一致性,会在开发中产生很多的问题;
如何获取state的结果
import React, { Component } from 'react'
export default class anli extends Component {
constructor(props){
super(props);
this.state={
counter:0,
message:'hi'
}
}
render() {
return (
<div>
<button onClick={e=>this.increment()}>改字段</button>
<h2>{this.state.message}</h2>
</div>
)
}
componentDidUpdate(){
// 方式二:获取异步更新的state
console.log(this.state.message)
}
increment(){
//方式一:获取异步更新后的数据
// setState(更新的state,回调函数)
this.setState({
message:'hello'
},()=>{
console.log('message',this.state.message)
})
}
}
同步更新setState
说明一下,我测试的并不是这样,还是异步。我目前还未找到原因
setState合并时进行累加
this.setState((prevState,props)=>{
return {
counter:preState.counter+1
}
})
React更新机制
React在props或state发生改变时,会调用React的render方法,会创建一颗不同的树
react性能优化
- 列表中keys的作用
- 组件嵌套的render调用
key的注意事项
- key应该是唯一的
- key不要使用随机数(随机数在下一次render时,会重新生成一个数字)
- 使用index作为key,对性能是没有优化的
shouldComponentUpdate 用法
shouldComponentUpdate(nextProps,nextState){
// 返回true,调用render方法。返回false,不调用remder方法
if(this.state.counter !== nextState.counter){
return true
}
return false;
}
render 只想改变一次 ,继承pureComponent(不能解决函数式再次渲染)
函数组件使用memo
import React, { Component, PureComponent,memo } from 'react'
// Header
const MemoHeader = memo(
function Header(){
console.log('Header 被调用了')
return <h2>我是header组件</h2>
}
)
// Main
class Main extends Component{
render(){
console.log('main 被调用')
return <h3>我是main组件</h3>
}
}
// banner
class Banner extends PureComponent{
render(){
console.log('banner 被调用')
return <h3>我是banner组件</h3>
}
}
export default class anli extends PureComponent {
constructor(props){
super(props);
this.state={
counter:0,
message:'hi'
}
}
render() {
console.log('APP render函数被调用')
return (
<div>
<MemoHeader></MemoHeader>
<Banner></Banner>
<Main></Main>
<h2>当前计数:{this.state.counter}</h2>
<button onClick={e=>this.changeText()}>改文本</button>
<button onClick={e=>this.increment()}>改文本</button>
</div>
)
}
changeText(){
this.setState({
message:'hello0'
});
}
increment(){
this.setState({
counter:this.state.counter+1
})
}
}
问题:
- 全局事件传递events
- setState传递的数据需要是不可变的数据
setState不可变
insertData(){
const newFriends = [...this.state.friends];
newFriends.push[{name:'tom',age:20}]
this.setState({
friends:newFriends
})
}
全局事件传递
安装events
yarn add events
import React, { PureComponent } from 'react'
import {EventEmitter} from 'events'
// 事件总线:event bus
const eventBus = new EventEmitter();
class Home extends PureComponent{
// 添加事件监听
componentDidMount(){
eventBus.addListener('sayHello',this.handleSayHelloListener)
}
// 取消事件监听
componentWillUnmount(){
// 取消所有的sayhello事件
eventBus.removeListener('sayHello',this.handleSayHelloListener)
}
handleSayHelloListener(num,message){
console.log(num,message)
}
render(){
return (
<div>
Home
</div>
)
}
}
class Profile extends PureComponent{
render() {
return (
<div>
Profile
<button onClick={e=>this.emmitEvent()}>点击Profile</button>
</div>
)
}
emmitEvent(){
eventBus.emit('sayHello','hello home',123)
}
}
export default class anli extends PureComponent {
render() {
return (
<div>
<Home />
<Profile />
</div>
)
}
}
受控和非受控组件
1.如何使用ref
创建refs来获取对应的DOM。
import React, { PureComponent,createRef } from 'react'
export default class anli extends PureComponent {
constructor(props){
super(props);
this.titleRef = createRef();
this.titleEl = null
}
render() {
return (
<div>
{/* ref=字符串/对象/函数 */}
<h2 ref='titleRef'>hello</h2>
{/* 目前react推荐的方式 */}
<h2 ref={this.titleRef}>react</h2>
<h2 ref={(arg)=>{this.titleEl=arg}}>hello</h2>
<button onClick={e=>this.changeText()}>改变文本</button>
</div>
)
}
changeText(){
// 1. 使用方式一:字符串(不推荐)
this.refs.titleRef.innerHTML = 'react'
// 2.使用方式二:对象方式
this.titleRef.current.innerHTML = 'hello javascript'
//3.回调函数方式
this.titleEl.innerHTML='functiona'
}
}
受控组件
我的理解就是 表单,双向绑定
import React, { PureComponent } from 'react'
export default class anli extends PureComponent {
constructor(props){
super(props);
this.state = {
username:'',
password:'',
vaild:''
}
}
render() {
return (
<div>
<form onSubmit={e=>this.handleSubmit(e)}>
<label htmlFor="username">
用户:
<input type="text"
id='username'
name='username'
value={this.state.username}
onChange={e=>this.handleChange(e)}/>
</label>
<label htmlFor="password">
密码:
<input type="text"
id='password'
name='password'
value={this.state.password}
onChange={e=>this.handleChange(e)}/>
</label>
<label htmlFor="vaild">
验证:
<input type="text"
id='vaild'
name='vaild'
value={this.state.vaild}
onChange={e=>this.handleChange(e)}/>
</label>
<input type="submit" value='提交' />
</form>
</div>
)
}
handleSubmit(event){
// 取消默认行为
event.preventDefault();
}
handleChange(event){
this.setState({
// 计算属性名
[event.target.name]:event.target.value
})
}
}