一、
函数组件没有this对象,也没有生命周期
hooks是在16.8以后才有的,也就是函数组件是后来添加的,
它的原理就是把类组件的render方法进行抽取实现的
函数组件与hooks
1.useState -- 定义一个state数据 useState为什么会在第二个参数是函数?因为react都是单向数据流,更新state数据需要调用方法, 所以第二个参数是一个执行更新数据的函数 第二个参数,是否是异步的?肯定是异步的,那么怎么解决,可以使用Promise、setTimeout、requestAnimationFrame来解决
//在react中只有props和state数据发生变化,才会引起组件的更新
//在函数组件中要定义state数据,就必须使用useState钩子函数,来定义数据对象和更新数据对象的方法
import React,{useCallback,useEffect,useMemo,useState} from 'react'
function List(){
console.log('------ 执行组件渲染')
//使用解构赋值来定义数据和更新数据的方法
const [salaryList,setSalaryList] = useState([])
//const [totalAmount,setTotalAmount]=useState([])
2.useEffect -- 副作用 监听依赖来实现类似于vue的watch属性,
如果依赖发生变化会执行回调 (这里不能写成死循环)
如果是没有依赖,那么props和state数据发生变化都会引起执行 如果依赖为一个空数组:
第一个回调参数相当于componentDidMount生命周期,如果函数中有返回一个函数CB,那么CB函数相当于componentWillUnmount生命周期
//使用解构赋值来定义数据和更新数据的方法
const [salaryList,setSalaryList] = useState([])
//有类似于类组件的生命周期的一个钩子函数 -- 有一个空依赖的副作用钩子函数
//useEffect(async function() { //副作用回调函数一定不能为一个异步方法,也就是不能在这里使用async + awawit
useEffect(function(){
//这个是副作用用于执行副作用业务方法的回调函数
getList().then(list =>{
setSalaryList(list)
//定义一个resize事件的回调函数,因为在卸载组件的时候,需要注销resize事件的第二个参数
function resizeEvt(){
console.log('-------- resize event')
window.addEventListener('resize',resizeEvt)
//在副作用钩子函数中返回一个函数,那么这个函数可以作为卸载生命周期 componentWillUnmount
return function(){
console.log('-------- componentWillUnmount')
window.removeEventListener('resize',resizeEvt)
},[])
3.useMemo: 在react中有一个useMemo钩子函数和vue的computed功能一致,是用来监听依赖变化,然后计算一个结果并缓存这个结果
第一个为计算函数,一定要返回计算结果
第二个为计算依赖项,当依赖项发生变化的时候,会执行回调重新计算结果值并更新缓存
const totalAmount=useMemo(function(){
return salaryList.reduce((res,it)=>{
if(!!it.amount) res += it.amount
return res
},0) //默认初始值为0
},[salaryList]) // 依赖项计算对象变量
4.useCallback():
因为function命名的函数会被反复定义,那么当前组件,这个方法会被定义两次,那么在内存中就会占用两份
定义一个回调函数,并缓存这个回调函数,当数据发生变化的时候,会更新回调函数,而不是重新定义,可以减少对内存消耗
有两个参数:(...args:[]) =>any,定义回调函数,表示回调函数可以接收很多参数
deps:React.DependencyList 是一个必传参数,为DependencyList回调函数依赖
为了优化内存,所以方法应该定义为一个函数对象,然后这个对象可以缓存到内存中 --所以可以用useCallback钩子函数来定义回调函数
所以当前回调方法中的salaryList为空数组,如果要有值,那么在赋值以后,或则salaryList数据发生变化的时候,应该更新回调函数
//遍历数据,然后对比id,如果id相等,则表示是修改这条数据的税率
const calcFunc = useCallback(function(id){
let _list = salaryList.reduce((res,it)=>{
if(it.id=== id){
it.rate = Math.ceil(Math.random() * 42 + 3 ) / 100
it.amount=it.base + it.jx - it.rateAmount
res.push(it)
return res
},[])
setSalaryList(_list)
//当数组发生变化以后,需要进行观察,当数据有值的时候,需要计算税率以及实发薪资 --
//这一点在vue中使用watch + deep深度监听属性是一样
//watch:{
// salaryList:{
// deept:true,
// handler:function(_list){}
//在react中如何实现 -- 当salaryList发生变化以后,会引起一些副作用
},[salaryList])
react函数组件在dom上绑定事件的用法
{/* calcFunc 函数是onClick事件的回调函数 */}
<button onClick={calcFunc.bind(null,it.id)}>计算</button>
//underfind 是未定义值,null是对象,函数里没有this就用null来传递