欢迎来到我的博客
📔博主是一名大学在读本科生,主要学习方向是前端。
🍭目前已经更新了【Vue】、【React–从基础到实战】、【TypeScript】等等系列专栏
🛠目前正在学习的是🔥 R e a c t 框架 React框架 React框架🔥,中间穿插了一些基础知识的回顾
🌈博客主页👉codeMak1r.小新的博客
本文被专栏【React–从基础到实战】收录
🕹坚持创作✏️,一起学习📖,码出未来👨🏻💻!
只要执行setState(),即使不改变状态数据,组件也会重新render();
this.setState({}); // 不改变状态,此时也会重新render()
- 1
- 2
只要当前组件重新render(),就会自动重新render子组件
即使子组件没有用到父组件的任何数据 ==> 效率低;
只有当组件的state或者props数据发生改变时才重新render()
Component中的shouldComponentUpdate()总是返回true
重写shouldComponentUpdate()方法
比较新旧state或者props数据,如果有变化才返回true,如果没有返回false
使用PureComponent
PureComponent重写了shouldComponentUpdate(),只有state或者props数据有变化才返回true
注意⚠️:
只是进行state和props数据的浅比较,如果只是数据对象内部数据变了,返回false;
不要直接修改state数据,而是要产生新数据
项目中一般使用PureComponent来优化。
// 父组件this.setState({});但是没有修改数据,组件就不会render
shouldComponentUpdate(nextProps, nextState) {
console.log(this.props, this.state) //目前的props和state
console.log(nextProps, nextState) // 要变化的目标props和state
if (this.state.xxx=== nextState.xxx) return false
else return true
}
判断状态更新前后的同一数据的值是否相同
若相同,则shouldComponentUpdate返回false(不render)
若不同,则shouldComponentUpdate返回true(允许render)
import React, { PureComponent } from 'react'
export default class Parent extends PureComponent{}
class Child extends PureComponent{}
PureComponent内部重写了shouldComponentUpdate方法,不用我们自己手写。
我们再来看前面提到的PureComponent存在的问题:
PureComponent
进行的是数据的浅比较
,也就是说,在修改状态数据时,不可以const obj = this.state obj.carName = 'Porsche-911 GT3 RS' this.setState(obj)
- 1
- 2
- 3
这样修改数据,只是对原state对象内的值做了修改,但是对象的引用地址没变!!
在
PureComponent
看来,引用地址没变时,组件内部的shouldComponentUpdate
返回false,也就不会重新render,数据更新就失败了。正确的更新状态应该是:
this.setState({ carName: 'Porsche-911 GT3 RS' });
- 1
这样修改数据,就是用一个新对象
{ carName: 'Porsche-911 GT3 RS' }
替换了原来的state对象,数据的引用地址变化了,那么PureComponent组件内部的shouldComponentUpdate返回true,组件重新render,数据更新成功。
错误边界(ErrorBoundary):用来捕获后代组件错误,渲染出备用界面。
所谓的边界,也就是把错误控制在一定范围内。比如后端的数据返回的是undefined
或者返回的数据类型出现错误,又或者是其他的一些不可控的、未知的错误出现时,在页面上直接显示报错信息显然是不对的。这个时候,我们就应该把错误控制在可控范围内,一旦错误超出可控范围,我们直接在页面中“安抚”一下用户,可以提示用户:“网络繁忙请稍后重试”这样的信息,直接甩锅给运营商!(doge)
比如,子组件中要展示的页面需要发送请求给服务器,使用后端返回的数据进行页面的展示。
那么,在数据无异常的时候,正常地展示正常的页面;
在数据出错的时候,告诉用户:网络繁忙请稍后重试!
在这种情况下我们就可以使用错误边界来解决。
错误边界一般是在容易发生错误的组件的父组件中处理。
只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误。
错误边界需要将错误限制在发生错误的组件当中,不要让错误扩散到上层组件。
getDerivedStateFromError配合componentDidCatch
state = {
hasError: false //用于标识子组件是否产生错误
}
// 如果当前组件的子组件出现了任何报错,都会调用这个钩子
static getDerivedStateFromError(error) {
console.log(error)
return { hasError: true }
}
这样的话,渲染子组件时就可以这样:
{this.state.hasError ? <h2>当前网络不稳定,稍后重试...</h2> : <Child />}
如果子组件出现任何报错,都不会干扰到其他组件的渲染,而只是在子组件的位置显示一行字:当前网络不稳定,稍后重试…
上面的代码配合componentDidCatch
export default class Parent extends Component {
state = {
hasError: '' //用于标识子组件是否产生错误
}
// 如果当前组件的子组件出现了任何报错,都会调用这个钩子
static getDerivedStateFromError(error) {
console.log(error)
return { hasError: error }
}
// 如果组件在渲染的过程中,子组件出现了问题引发了错误,就会调用这个钩子
componentDidCatch(error, info) {
console.log(error, info)
// 这里一般用来统计错误次数,反馈给服务器,用于告知服务器维护人员这里有bug。
}
render() {
return (
<div className='parent'>
<h2>我是Parent组件</h2>
{this.state.hasError ? <h2>当前网络不稳定,稍后重试...</h2> : <Child />}
</div>
)
}
}
Vue中:
React中:
- 使用
children props
:通过组件标签体传入结构- 使用
render props
:通过组件标签属性传入结构,而且可以携带数据,一般用render函数属性
<A>
<B>xxxx</B>
</A>
{this.props.children}
问题:如果B组件需要A组件内的数据 ==> 做不到
<A render={(data) => <C data={data}</C>}</A>
A组件:{this.props.render(内部state数据)}
C组件:读取A组件传入的数据显示 {this.props.data}
比如,有一个Parent组件为父组件,A组件为子组件,B组件为孙组件。
A组件自身有一个状态为name,值为tom。B组件如果要想使用A组件的状态的话,正常的做法是:
Parent组件:
class Parent extends Component {
render() {
return (
<div>
<A/>
</div>
)
}
}
A组件:
class A extends Component {
state = { name:'tom' }
render() {
return (
<div>
<B name={this.state.name}/>
</div>
)
}
}
将子组件A的name属性通过props传递给孙组件B。
不过,我们还可以使用render props来完成:
Parent组件:
class Parent extends Component {
render() {
return (
<div>
{/* 2.接收name参数,再传给B */}
<A render={(name) => <B name={name}/>} />
</div>
)
}
}
A组件:
class A extends Component {
state = { name:'tom' }
render() {
const { name } = this.state
return (
<div>
{/* 1.把name通过this.props.render()传过去 */}
{this.props.render(name)}
</div>
)
}
}
这样,B组件也可以使用到A组件的状态,name被保存在B组件的this.props.name
上。
props
(1)children props
(2)render props
消息订阅与发布
PubSub、event等等
集中式管理
redux、dva、mobx等等
Context
生产者-消费者模式
父子组件:props
兄弟组件:消息订阅-发布、集中式管理
祖孙组件(跨级组件):消息订阅-发布、集中式管理、Context(开发用的少,封装插件用的多)