2021.6.19更:
useImperativeHandle的第一个参数为ref句柄,即父组件传递到子组件的ref属性,
useImperativeHandle和子组件第二位预留参数ref的使用需要forwardRef高阶组件的配合:
但有时候我们不想使用forwardRef高阶组件,即子组件预留的第二位参数ref失效
这时候需要手动往子组件props参数中传递xxxref,通过xxxref和useImperativeHandle一样能达到获取子组件属性和api的作用,且不需要使用forwardRef高阶组价了
useCallBack & useMemo
用法:
useMemo 和 useCallback 接收的参数都是一样,第一个参数为回调 第二个参数为要依赖的数据
const ds = useMemo(() => new DataSet({xxx}), []); // 缓存了new出来的DataSet实例
const fn = useCallBack(() => {}, []); // 仅仅是缓存这个函数 不让fn随便刷新
共同点
1.仅仅 依赖数据 发生变化, 才会重新计算结果,也就是起到缓存的作用。
区别点
1.useMemo 计算结果是 return 回来的值, 主要用于 缓存计算结果的值 ,应用场景如: 需要 计算的状态
2.useCallback 计算结果是 函数, 主要用于 缓存函数,应用场景如: 需要缓存的函数,因为函数式组件每次任何一个 state 的变化 整个组件 都会被重新刷新,一些函数是没有必要被重新刷新的,此时就应该缓存起来,提高性能,和减少资源浪费。
forwardRef
用法:
1.父组件传递子组件ref,子组件拿到ref并放到对应的dom上,例如Input,父组件就能调用子组件input的相关api(涉及dom)
useImperativeHandle
用法:
父组件传递给子组件的ref,通过useImperativeHandle可以拿到子组件所有的变量和api
useImperativeHandle(ref, ()=>({
[api],
[变量],
}))
拓展思考
虽然forwardRef和useImperativeHandle配合使用完全能达到想要的父调子所有api和dom的效果,但是使用forwardRef需要把函数组件当参数才能起到转发父组件props和ref的作用,但是往往一个组件需多个高阶组件嵌套,例如observer(),connect()等混合使用时, 它们如何一起使用呢?
const Index = forwardRef(() => {});
const Index = observer(() => {});
const Index = connect(() => {});
lodash 提供了 'compose' api供合并执行函数:
compose(connect(arg), observer(agr2), ...)(Index)合并执行的方法
observer, connect等是高阶组件,高阶组件通过 1. 属性继承 2. 反向代理3.渲染劫持...从而达到api实现的效果,例如:
把global参数传递进去
connect(global = {})(Index) // 先执行const fn = connect(gloabl)
高阶函数接受参数组件作为参数返回一个新的组件
const NewCom = fn(Index)
最后我们再export default NewCom
合并在一起就是
export default compose(connect(global = {}), observer(global = {}), forwardRef())(Index);