Vue模板中复用带参函数返回值的优化方案咨询
解决Vue模板中带参数函数重复调用的问题
方案1:给函数加手动缓存
自己实现函数的缓存逻辑,相同参数直接返回缓存结果,避免重复计算。同时监听依赖数据变化,及时清空缓存防止过期。
示例代码:
<script setup> import { ref, watchEffect } from 'vue' const el = ref(/* 你的业务数据 */) const steps = ref(/* 你的业务数据 */) // 用对象存储缓存,参数组合作为键名 const valCache = ref({}) // 监听依赖数据,数据变化时清空缓存 watchEffect(() => { valCache.value = {} }) const getVal = (i, attrKey) => { const cacheKey = `${i}-${attrKey}` // 缓存存在直接返回 if (valCache.value[cacheKey] !== undefined) { return valCache.value[cacheKey] } // 这里写原有的计算逻辑 const result = /* 根据i和attrKey计算得到的结果 */ valCache.value[cacheKey] = result return result } </script> <template v-for="attr in el.attrs"> <div v-for="(step, i) in steps" :title="getVal(i, attr.key)"> {{ getVal(i, attr.key) ? '◇' : '-' }} </div> </template>
这个方案改动最小,不用调整模板结构,缓存仅在依赖数据变化时重置,性能开销极低。
方案2:预计算所有结果(用computed生成映射表)
提前把所有i和attr.key组合对应的结果计算好,存在computed映射表里,模板直接取值,彻底避免函数调用。
示例代码:
<script setup> import { computed } from 'vue' const el = ref(/* 你的业务数据 */) const steps = ref(/* 你的业务数据 */) // 预计算所有组合的结果,生成嵌套映射表 const valMap = computed(() => { const map = {} el.value.attrs.forEach(attr => { map[attr.key] = {} steps.value.forEach((_, i) => { // 这里写原有的计算逻辑 map[attr.key][i] = /* 根据i和attr.key计算得到的结果 */ }) }) return map }) </script> <template v-for="attr in el.attrs"> <div v-for="(step, i) in steps" :title="valMap[attr.key][i]"> {{ valMap[attr.key][i] ? '◇' : '-' }} </div> </template>
这个方案性能最优,computed仅在依赖数据变化时重新计算,模板直接读取属性,没有函数调用开销。适合数据量不大的业务场景。
方案3:拆分子组件
把每个循环项拆成独立子组件,子组件接收index和attrKey作为props,内部用computed计算值,每个子组件的computed只会计算一次,模板直接复用结果。
子组件StepItem.vue:
<script setup> import { computed } from 'vue' const props = defineProps(['index', 'attrKey', 'steps', 'el']) // 子组件内部用computed计算值,自动缓存 const itemVal = computed(() => { // 这里写原有的计算逻辑 return /* 根据props.index和props.attrKey计算得到的结果 */ }) </script> <template> <div :title="itemVal"> {{ itemVal ? '◇' : '-' }} </div> </template>
父组件使用:
<script setup> import StepItem from './StepItem.vue' </script> <template v-for="attr in el.attrs"> <StepItem v-for="(step, i) in steps" :key="`${attr.key}-${i}`" :index="i" :attr-key="attr.key" :steps="steps" :el="el" /> </template>
这个方案适合逻辑复杂的场景,拆分后代码更清晰,子组件的computed会自动根据props变化更新,不会出现重复计算问题。
为什么用ref存结果会触发递归更新?
你之前遇到的警告,是因为在渲染阶段调用的getVal里修改ref,会触发组件重新渲染;而重新渲染时又会再次调用getVal修改ref,形成无限循环。所以不能在渲染函数里直接修改响应式变量,必须把缓存逻辑和渲染逻辑解耦。
内容的提问来源于stack exchange,提问作者imv
相关产品推荐
相关产品推荐

