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