一、 函数组件没有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来传递