在类组件每一次重新渲染时,会执行一遍 render()
内的代码
在函数式组件每一次重新渲染时,会重新执行一遍函数组件内的所有代码
且组件内声明的语句有一个特色:在不同的生命周期下,声明的同名变量在不同的生命周期下,在 react 看来是不同的变量,这点需要在组件更新时关注
如下面的例子代码:
类组件和函数式都是同一个作用:更新的时候添加一个点击事件,通过更改鼠标坐标并点击更改state从而发生更新【添加事件函数addEventListener()
对于完全相等的事件函数不会多次添加】
类组件的效果:每次更新时点击事件不会发生叠加,即如果点击三次,则再点击时只会打印一条 Class_inner
函数式组件的效果:每次更新时点击事件会发生点击,即如果点击三次,再次点击时会不止打印一条 Fun_inner
,说明此时绑定的事件有多个,多个事件同时生效打印了多次
import React, { Component } from 'react'
export default class TestDemo extends Component {
constructor() {
super()
this.state = {
staus:true,
positionX:0
}
}
updataMouse = (e) => {
console.log('Class_inner')
this.setState({
positionX:e.clientX
})
}
componentDidMount() {
document.addEventListener('click', this.updataMouse)
}
componentDidUpdate() {
document.addEventListener('click', this.updataMouse)
}
render() {
return (
<div></div>
)
}
}
import React, {useState, useEffect} from 'react'
export default function FunDemo() {
const [staus, setStaus] = useState(true)
const [positionX, setPositionX] = useState(0)
const updataMouse = (e) => {
console.log('Fun_inner')
setPositionX(e.clientX)
}
useEffect(() => {
document.addEventListener('click', updataMouse)
})
return (
<div></div>
)
}
这是因为函数式组件的 updataMouse
被多次声明的原因,改写代码成下面,发现只有 updataMouse2
函数会出现事件叠加的现象,而 updataMouse1
事件无论组件更新了多少次都只会打印一条信息
说明了只有函数式组件内的代码在更新渲染时会被重新执行,声明了多次 updataMouse2
函数,且不同生命周期内的同名函数实际上在 react 看来是不同的,因此会多次绑定,因此最终就会产生事件叠加的效果
【class组件更新时只会执行render内的方法,因此更新时不会重新声明事件函数】
import React, {useState, useEffect} from 'react'
const updataMouse1 = (e) => {
console.log('inner1')
}
export default function FunDemo() {
const [staus, setStaus] = useState(true)
const [positionX, setPositionX] = useState(0)
const updataMouse2 = (e) => {
console.log('inner2')
setPositionX(e.clientX)
}
useEffect(() => {
document.addEventListener('click', updataMouse1)
document.addEventListener('click', updataMouse2)
})
return (
<div></div>
)
}
不同声明周期下声明的同名变量会被 react 看做是不同的变量,如果该变量没有被继续引用则会被当垃圾清理,但是如果保持对这些变量的引用(往往都是函数调用),就像使用闭包没有及时断开引用一样,会让这些变量无法被清理,因此就会造成了事件叠加,需要手动地将这些引用及时清理掉
import React, {useState, useEffect} from 'react'
export default function FunDemo() {
const [staus, setStaus] = useState(true)
const [positionX, setPositionX] = useState(0)
const updataMouse = (e) => {
console.log('Fun_inner')
setPositionX(e.clientX)
}
useEffect(() => {
document.addEventListener('click', updataMouse)
return () => {
removeEventListener('click', updataMouse)
}
})
return (
<div></div>
)
}