react useMemo和 useEffect和 useCallback
useEffect
effect只能在DOM更新后触发
useMemo
传入 useMemo 的函数会在渲染期间执行,即在DOM更新前触发的,就像官方所说的,类比生命周期就是shouldComponentUpdate
useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;
useCallback
useCallback跟useMemo比较类似,但它返回的是缓存的函数。
const fnA = useCallback(fnB, [a])
上面的useCallback会将我们传递给它的函数fnB返回,并且将这个结果缓存;当依赖a变更时,会返回新的函数。既然返回的是函数,我们无法很好的判断返回的函数是否变更,所以我们可以借助ES6新增的数据类型Set来判断.
使用场景:
- 有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件发生任何更新,子组件也同样会执行一次重新渲染,而当父组件的 callback 没有变化时,子组件依赖的props中的 callback 也再次更新就是没有必要的,所以我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新,优化渲染性能;
- 所有依赖本地状态或props来创建函数,需要使用到缓存函数的地方
总结:useMemo和useCallback这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数。
参考:https://blog.csdn.net/hsany330/article/details/106122228
https://blog.csdn.net/sinat_17775997/article/details/94453167
react useMemo和 vue computed
https://blog.csdn.net/weixin_43720095/article/details/104950676
react useMemo类似 vue 的 computed,不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo
把“创建”函数和依赖项数组作为参数传入 useMemo,避免不必要的执行渲染,以达到优化性能的目的
- 缓存计算结果的值
- 计算结果是 return 的值
Vue v-memo
记住一个模板的子树。元素和组件上都可以使用。该指令接收一个固定长度的数组作为依赖值进行记忆比对。如果数组中的每个值都和上次渲染的时候相同,则整个该子树的更新会被跳过
<div v-memo="[valueA]">
...
</div>
当组件重新渲染的时候,如果valueA都维持不变,那么对这个<div>以及它的所有子节点的更新都将被跳过。事实上,即使是虚拟 DOM 的 VNode 创建也将被跳过,因为子树的记忆副本可以被重用。
使用场景
假设请求接口返回来了1000+条数据。 前端需要做筛选。 选出符合条件的数据进行展示。 如果没有符合条件的。则保持上次的展示。
<template> <div class="home"> <input type="text" v-model="food"> <!-- v-memo中“valueA”若不发生变化,则不会进行更新 --> <div v-memo="[valueA]"> <div class="box" v-for="item in arr" :key="item"> {{ foodObj[food] }} </div> </div> </div> </template> <script setup> import { ref, watch } from "vue" // 先生成1000条数据 const arr = new Array(1000) // 定义一个对象 const foodObj = { 'hb':' ', 'nc':' ', 'st':' ', } // input绑定的值 const food = ref('hb') // v-memo依赖的值 const valueA = ref(0) // 如果数据发生变化,并且在foodObj对象中存在。视图进行更新。否则视图不更新。 watch(()=>food.value,()=>{ if(Object.keys(foodObj).includes(food.value)){ valueA.value = Math.ceil(Math.random()*10000) } }) </script> <style> .box { display: inline-block; 80px; } </style>
注意点
v-for内部使用v-memo是无效的。